ExcelWorksheet.ts 3.72 KB
Newer Older
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
1
import { EventEmitter } from 'events';
Fullarton's avatar
Fullarton committed
2 3
import * as xlsx from 'excel4node';
import * as MessageFormat from 'messageformat';
4
import { Document } from 'mongoose';
5
import MemberDAO from '../db/MemberDAO';
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
6
import { ILeaderBoardItemBase } from '../interfaces/leaderboard/ILeaderBoardItemBase';
7
import { IQuizBase } from '../interfaces/quizzes/IQuizEntity';
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
8
import { Leaderboard } from '../lib/leaderboard/leaderboard';
9
import { MemberModelItem } from '../models/member/MemberModel';
10 11
import { excelDefaultWorksheetOptions } from './lib/excel_default_options';
import { ExcelTheme } from './lib/excel_default_styles';
Fullarton's avatar
Fullarton committed
12 13 14 15 16

export abstract class ExcelWorksheet {
  get columnsToFormat(): number {
    return this._columnsToFormat;
  }
17

18
  get quiz(): IQuizBase {
Fullarton's avatar
Fullarton committed
19 20
    return this._quiz;
  }
21

Fullarton's avatar
Fullarton committed
22 23 24
  get createdAt(): string {
    return this._createdAt;
  }
25

26
  get mf(): MessageFormat.Msg {
Fullarton's avatar
Fullarton committed
27 28
    return this._mf;
  }
29 30 31

  protected _ws: xlsx.Worksheet;

Fullarton's avatar
Fullarton committed
32 33 34
  get ws(): xlsx.Worksheet {
    return this._ws;
  }
35

36 37 38 39 40 41
  private _responsesWithConfidenceValue: Array<Document & MemberModelItem>;

  get responsesWithConfidenceValue(): Array<Document & MemberModelItem> {
    return this._responsesWithConfidenceValue;
  }

42 43 44
  protected _options: Object;
  protected _theme: ExcelTheme;
  protected _translation: string;
45
  private readonly _mf: MessageFormat.Msg;
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
46
  private readonly _createdAt: string;
47 48
  private readonly _quiz: IQuizBase;
  private _columnsToFormat: number;
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
49
  protected readonly loaded = new EventEmitter();
Fullarton's avatar
Fullarton committed
50

51
  protected constructor({ theme, translation, quiz, mf, questionIndex }) {
Fullarton's avatar
Fullarton committed
52 53 54 55 56 57 58
    this._theme = theme;
    this._translation = translation;
    this._quiz = quiz;
    this._mf = mf;
    this._createdAt = this.generateCreatedAtString();
    this._options = Object.assign({}, excelDefaultWorksheetOptions, {
      headerFooter: {
59
        firstHeader: mf('export.page_header', { createdAt: this._createdAt }),
Fullarton's avatar
Fullarton committed
60
        firstFooter: mf('export.page_footer'),
61
        evenHeader: mf('export.page_header', { createdAt: this._createdAt }),
Fullarton's avatar
Fullarton committed
62
        evenFooter: mf('export.page_footer'),
63
        oddHeader: mf('export.page_header', { createdAt: this._createdAt }),
Fullarton's avatar
Fullarton committed
64 65
        oddFooter: mf('export.page_footer'),
        alignWithMargins: true,
66 67
        scaleWithDoc: false,
      },
Fullarton's avatar
Fullarton committed
68 69 70
    });

    this._columnsToFormat = 4;
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

    MemberDAO.getMembersOfQuiz(this._quiz.name).then(members => {
      if (questionIndex) {
        this._responsesWithConfidenceValue = members.filter(nickname => {
          return nickname.responses[questionIndex].confidence > -1;
        });
      } else {
        this._responsesWithConfidenceValue = members.filter(nickname => {
          return nickname.responses.some(responseItem => responseItem.confidence > -1);
        });
      }

      if (this._responsesWithConfidenceValue.length > 0) {
        this._columnsToFormat++;
      }
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
86 87

      this.loaded.emit('load');
88 89
    });

Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
90
    if (this._quiz.sessionConfig.nicks.restrictToCasLogin) {
Fullarton's avatar
Fullarton committed
91 92 93 94 95 96 97 98 99 100 101
      this._columnsToFormat += 2;
    }
  }

  protected generateCreatedAtString(): string {
    const date = new Date();
    const dateYMD = `${this.prefixNumberWithZero(date.getDate())}.${this.prefixNumberWithZero(date.getMonth() + 1)}.${date.getFullYear()}`;
    const dateHM = `${this.prefixNumberWithZero(date.getHours())}:${this.prefixNumberWithZero(date.getMinutes())}`;
    return `${dateYMD} ${this._mf('export.exported_at')} ${dateHM} ${this._mf('export.exported_at_time')}`;
  }

Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
102
  protected async getLeaderboardData(): Promise<Array<ILeaderBoardItemBase>> {
Fullarton's avatar
Fullarton committed
103
    const leaderBoard = new Leaderboard();
104
    const { correctResponses } = await leaderBoard.buildLeaderboard(this.quiz);
Christopher Mark Fullarton's avatar
Christopher Mark Fullarton committed
105
    return leaderBoard.sortBy(correctResponses, 'score');
Fullarton's avatar
Fullarton committed
106
  }
107 108 109 110

  private prefixNumberWithZero(num: number): string {
    return `${num < 10 ? '0' : ''}${num}`;
  }
Fullarton's avatar
Fullarton committed
111
}