Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | 17x 17x 17x 17x 17x 17x 17x 13x 47x 47x 63x 3x 3x 1x 2x 7x 64x 64x 7x 60x 60x 68x 4x 1x 2x 4x 2x 1x 1x 2x 2x | import _ from 'lodash'; import {proto} from '../constants'; import * as utils from '../utils'; import * as siProtocol from '../siProtocol'; import * as storage from '../storage'; import {IRaceResultData} from './IRaceResultData'; import {makeStartZeroTime, monotonizeRaceResult, prettyRaceResult} from './raceResultTools'; export type SiCardType<T extends BaseSiCard> = { new(cardNumber: number): T, typeSpecificInstanceFromMessage: (message: siProtocol.SiMessage) => T|undefined, }; const initialRegistry: utils.NumberRangeRegistry<SiCardType<BaseSiCard>> = new utils.NumberRangeRegistry(); export interface ISiMainStation { sendMessage: ( message: siProtocol.SiMessage, numResponses?: number, timeoutInMiliseconds?: number, ) => Promise<number[][]>; } export abstract class BaseSiCard { // abstract static maxNumPunches: number; static NumberRange: typeof utils.NumberRange = utils.NumberRange; static cardNumberRangeRegistry: utils.NumberRangeRegistry<SiCardType<BaseSiCard>> = initialRegistry; static resetNumberRangeRegistry(): void { this.cardNumberRangeRegistry = new utils.NumberRangeRegistry(); } static registerNumberRange<T extends BaseSiCard>( firstCardNumberInRange: number, firstCardNumberAfterRange: number, siCardType: SiCardType<T>, ): void { const cardNumberRange = new utils.NumberRange(firstCardNumberInRange, firstCardNumberAfterRange); this.cardNumberRangeRegistry.register(cardNumberRange, siCardType); } static getTypeByCardNumber<T extends BaseSiCard>(cardNumber: number): SiCardType<T>|undefined { return this.cardNumberRangeRegistry.getValueForNumber(cardNumber) as SiCardType<T>|undefined; } // abstract static getPunchOffset(index: number): number; static fromCardNumber(cardNumber: number): BaseSiCard|undefined { const cardType = this.getTypeByCardNumber(cardNumber); if (!cardType) { return undefined; } return new cardType(cardNumber); } static detectFromMessage(message: siProtocol.SiMessage): BaseSiCard|undefined { const possibleCards = this.cardNumberRangeRegistry.values .map((cardType) => cardType.typeSpecificInstanceFromMessage(message)) .filter((cardInstance) => cardInstance !== undefined); return possibleCards.get(0); } // abstract static typeSpecificInstanceFromMessage<Fields extends IBaseSiCardStorageFields>( // _message: siProtocol.SiMessage, // ): BaseSiCard<Fields>|undefined; public mainStation?: ISiMainStation|undefined; public raceResult: IRaceResultData&{cardNumber: number}; public storage: storage.ISiStorage<unknown> = {} as storage.ISiStorage<unknown>; constructor(cardNumber: number) { this.raceResult = {cardNumber: cardNumber}; } get cardNumber(): number { return this.raceResult.cardNumber; } read(): Promise<BaseSiCard> { return this.typeSpecificRead() .then(() => this); } getNormalizedRaceResult(): IRaceResultData { return makeStartZeroTime(this.getMonotonizedRaceResult()); } getMonotonizedRaceResult(): IRaceResultData { return monotonizeRaceResult(this.raceResult); } abstract typeSpecificRead(): Promise<void>; confirm(): Promise<number[][]> { if (!this.mainStation) { return Promise.reject(new Error('No main station')); } return this.mainStation.sendMessage({ mode: proto.ACK, }, 0); } toDict(): IRaceResultData { return this.raceResult; } toString(): string { return `${this.constructor.name}\n${prettyRaceResult(this.raceResult)}`; } } |