From 956b29e54b471a3226cfa6b661fcb84991b2a2c7 Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Wed, 19 Jul 2023 15:12:55 +0000 Subject: [PATCH 01/91] Implement Mesopotamian date, editing component & date converter (WiP) --- src/common/BrinkmanKings.tsx | 2 +- src/fragmentarium/domain/Date.ts | 178 + .../domain/DateConverter.test.ts | 74 + src/fragmentarium/domain/DateConverter.ts | 212 + src/fragmentarium/domain/FragmentDtos.ts | 20 + .../domain/dateConverterData.json | 17444 ++++++++++++++++ src/fragmentarium/domain/fragment.ts | 13 +- .../infrastructure/FragmentRepository.test.ts | 15 + .../infrastructure/FragmentRepository.ts | 5 + src/fragmentarium/ui/info/DateSelection.tsx | 270 + src/fragmentarium/ui/info/Details.tsx | 17 +- src/test-support/fragment-fixtures.ts | 6 +- src/test-support/test-fragment.ts | 15 + 13 files changed, 18266 insertions(+), 5 deletions(-) create mode 100644 src/fragmentarium/domain/Date.ts create mode 100644 src/fragmentarium/domain/DateConverter.test.ts create mode 100644 src/fragmentarium/domain/DateConverter.ts create mode 100644 src/fragmentarium/domain/dateConverterData.json create mode 100644 src/fragmentarium/ui/info/DateSelection.tsx diff --git a/src/common/BrinkmanKings.tsx b/src/common/BrinkmanKings.tsx index b9f8755b3..a7ad059a2 100644 --- a/src/common/BrinkmanKings.tsx +++ b/src/common/BrinkmanKings.tsx @@ -7,7 +7,7 @@ import BrinkmanKings from 'common/BrinkmanKings.json' import { Popover } from 'react-bootstrap' import HelpTrigger from 'common/HelpTrigger' -interface King { +export interface King { orderGlobal: number groupWith?: number dynastyNumber: string diff --git a/src/fragmentarium/domain/Date.ts b/src/fragmentarium/domain/Date.ts new file mode 100644 index 000000000..6c105cf60 --- /dev/null +++ b/src/fragmentarium/domain/Date.ts @@ -0,0 +1,178 @@ +//import produce, { castDraft, Draft, immerable } from 'immer' +//import { immerable } from 'immer' +//import _ from 'lodash' +import { King } from 'common/BrinkmanKings' +import { MesopotamianDateDto } from 'fragmentarium/domain/FragmentDtos' +import { romanize } from 'romans' + +export interface DateField { + value: string + broken?: boolean + uncertain?: boolean +} + +export interface MonthField extends DateField { + intercalary?: boolean +} + +export enum Ur3Calendar { + ADAB = 'Adab', + GIRSU = 'Girsu', + IRISAGRIG = 'Irisagrig', + NIPPUR = 'Nippur', + PUZRISHDAGAN = 'Puzriš-Dagan', + UMMA = 'Umma', + UR = 'Ur', +} + +export class Date { + era: King | string | undefined + year: DateField + month: MonthField + day: DateField + ur3Calendar?: Ur3Calendar + + constructor( + era: King | string | undefined, + year: DateField, + month: MonthField, + day: DateField, + ur3Calendar?: Ur3Calendar + ) { + this.era = era + this.year = year + this.month = month + this.day = day + this.ur3Calendar = ur3Calendar + } + + static fromJson(dateJSON: MesopotamianDateDto): Date { + const { era, year, month, day } = dateJSON + console.log(dateJSON, new Date(era, year, month, day)) + return new Date(era, year, month, day) + } + + toString(): string { + const dateParts = [ + this.yearToString(), + this.monthToString(), + this.dayToString(), + ] + return `${dateParts.join( + '.' + )}${this.eraToString()}${this.ur3CalendarToString()}` + } + + yearToString(): string { + return this.year.value + ? this.brokenAndUncertainToString('year', this.year.value) + : '∅' + } + + monthToString(): string { + const intercalary = this.month.intercalary ? '²' : '' + const month = Number(this.month.value) + ? romanize(Number(this.month.value)) + : this.month.value + return month + ? this.brokenAndUncertainToString('month', month + intercalary) + : '∅' + } + + dayToString(): string { + return this.day.value + ? this.brokenAndUncertainToString('day', this.day.value) + : '∅' + } + + brokenAndUncertainToString( + parameter: 'year' | 'day' | 'month', + element: string + ): string { + const { broken, uncertain } = this[parameter] + + return `${broken ? '⸢' : ''}${element}${broken ? '⸣' : ''}${ + uncertain ? '?' : '' + }` + } + + eraToString(): string { + const era = + this.era === 'seleucid' + ? 'SE' + : typeof this.era === 'string' + ? this.era + : this.era?.name ?? '' + return era ? ' ' + era : era + } + + ur3CalendarToString(): string { + return this.ur3Calendar ? `, ${this.ur3Calendar} calendar` : '' + } + + toGregorian(): string { + // ToDo: WiP, implement + return '' + } +} + +/* +export class Dates { + readonly dates: ReadonlyArray + + constructor(dates: Date[]) { + this.dates = dates + } + + static fromJson(datesJSON: readonly MesopotamianDateDto[]): Dates { + return new Dates(datesJSON.map((dateJson) => Date.fromJson(dateJson))) + } + + + isPresent(date: Date): boolean { + return this.dates.some( + (element) => + JSON.stringify(element.category) === JSON.stringify(date.category) + ) + } + + find(date: Date): Date | undefined { + return _.find( + this.dates, + (elem) => JSON.stringify(elem.category) === JSON.stringify(date.category) + ) + } + + insertWithOrder(date: Date, indexLookup: readonly string[][]): Dates { + return produce(this, (draft: Draft) => { + draft.dates = castDraft( + _.sortBy([...this.dates, date], (date) => + JSON.stringify(indexLookup).indexOf(JSON.stringify(date.category)) + ) + ) + }) + } + + delete(date: Date): Dates { + return produce(this, (draft: Draft) => { + draft.dates = castDraft( + this.dates.filter( + (elem) => JSON.stringify(elem) !== JSON.stringify(date) + ) + ) + }) + } + + replace(date: Date): Dates { + return produce(this, (draft: Draft) => { + const dates = _.cloneDeep(this.dates as Date[]) + const index = _.findIndex( + this.dates, + (content) => + JSON.stringify(content.category) === JSON.stringify(date.category) + ) + dates.splice(index, 1, date) + draft.dates = castDraft(dates) + }) + } + */ diff --git a/src/fragmentarium/domain/DateConverter.test.ts b/src/fragmentarium/domain/DateConverter.test.ts new file mode 100644 index 000000000..fd5771562 --- /dev/null +++ b/src/fragmentarium/domain/DateConverter.test.ts @@ -0,0 +1,74 @@ +import DateConverter from './DateConverter' + +describe('DateConverter', () => { + let babylonDate: DateConverter + + beforeEach(() => { + babylonDate = new DateConverter() + }) + + test('Set modern date', () => { + babylonDate.setModernDate(-310, 3, 3) + const expected = { + year: -310, + month: 3, + day: 3, + bcYear: '311', + julianDay: 1607892, + weekDay: 1, + babylonianDay: 29, + babylonianMonth: 11, + babylonianRuler: '4 Alexander IV Aegus', + seBabylonianYear: '0', + seMacedonianYear: '1', + arsacidYear: ' ', + babylonianLunation: 5393, + babylonianMonthLength: 29, + } + expect(babylonDate.calendar).toEqual(expected) + }) + + test('Set Babylonian date', () => { + // WiP. + // ToDo: Update to properly test. + babylonDate.setBabylonianDate(-200, 10, 1) + const expected = { + year: -625, + month: 11, + day: 27, + bcYear: '626', + julianDay: 1493107, + weekDay: 2, + babylonianDay: 1, + babylonianMonth: 9, + babylonianRuler: '1 Interregnum', + seBabylonianYear: '-314', + seMacedonianYear: ' ', + arsacidYear: ' ', + babylonianLunation: 1507, + babylonianMonthLength: 30, + } + expect(babylonDate.calendar).toEqual(expected) + }) + + test('Update year', () => { + babylonDate.updateYear(100) + expect(babylonDate.calendar.year).toBe(-210) + }) + + test('Update month', () => { + babylonDate.updateMonth(5) + expect(babylonDate.calendar.month).toBe(8) + expect(babylonDate.calendar.year).toBe(-310) + }) + + test('Update day', () => { + babylonDate.updateDay(10) + expect(babylonDate.calendar.day).toBe(13) + }) + + test('Get current day', () => { + babylonDate.calendar.day = 25 + expect(babylonDate.getCurrentDay()).toBe(25) + }) +}) diff --git a/src/fragmentarium/domain/DateConverter.ts b/src/fragmentarium/domain/DateConverter.ts new file mode 100644 index 000000000..8f9e9f9aa --- /dev/null +++ b/src/fragmentarium/domain/DateConverter.ts @@ -0,0 +1,212 @@ +import data from 'fragmentarium/domain/dateConverterData.json' + +export default class DateConverter { + calendar = { + year: 0, + month: 0, + day: 0, + bcYear: '', + julianDay: 0, + weekDay: 0, + babylonianDay: 0, + babylonianMonth: 0, + babylonianRuler: '', + seBabylonianYear: '', + seMacedonianYear: '', + arsacidYear: '', + babylonianLunation: 0, + babylonianMonthLength: 0, + } + + constructor() { + this.setModernDate(-310, 3, 3) + } + + setModernDate(year: number, month: number, day: number): void { + this.updateDate(year, month, day) + this.updateBabylonDate() + } + + updateYear(offset: number): void { + this.calendar.year += offset + this.updateBabylonDate() + } + + updateMonth(offset: number): void { + const { month: currentMonth } = this.calendar + const yearOffset = + offset > 0 && currentMonth + offset > 12 + ? 1 + : offset < 0 && currentMonth + offset < 1 + ? -1 + : 0 + const month = (currentMonth + offset + 12) % 12 || 12 + const year = this.calendar.year + yearOffset + this.updateDate(year, month, this.getCurrentDay()) + this.updateBabylonDate() + } + + updateDay(offset: number): void { + this.calendar.day += offset + this.updateBabylonDate() + } + + getCurrentDay(): number { + return this.calendar.day + } + + setBabylonianDate( + babylonianYear: number, + babylonianMonth: number, + babylonianDay: number + ): void { + const cjdn = this.computeCJDNFromBabylonian( + babylonianYear, + babylonianMonth, + babylonianDay + ) + console.log('!! cjdn', cjdn) + if (isNaN(cjdn)) { + throw new Error( + `Could not convert Babylonian date ${babylonianYear}/${babylonianMonth}/${babylonianDay} to a Julian date.` + ) + } + + const [year, month, day] = this.computeModernDateFromCJDN(cjdn) + if ([year, month, day].some(isNaN)) { + throw new Error(`Could not convert Julian date ${cjdn} to a modern date.`) + } + + this.updateDate(year, month, day) + this.updateBabylonDate() + } + + private computeCJDNFromBabylonian( + babylonianYear: number, + babylonianMonth: number, + babylonianDay: number + ): number { + const i = data.babylonYmPd.findIndex( + (yearMonth) => + Math.floor(Math.abs(yearMonth)) >= babylonianYear && + Math.floor( + 100 * (Math.abs(yearMonth) - Math.floor(Math.abs(yearMonth))) + 0.001 + ) === babylonianMonth + ) + + if (i === -1) { + throw new Error('Could not find matching Babylonian date in data.') + } + return data.babylonCjdnPd[i - 1] + babylonianDay - 1 + } + + private computeModernDateFromCJDN(cjdn: number): [number, number, number] { + const b = cjdn + 1524 + const c = Math.floor((b - 122.1) / 365.25) + const d = Math.floor(365.25 * c) + const e = Math.floor((b - d) / 30.6001) + + const day = b - d - Math.floor(30.6001 * e) + const month = e < 14 ? e - 1 : e - 13 + const year = month > 2 ? c - 4716 : c - 4715 + + return [year, month, day] + } + + updateBabylonDate(): void { + const day = this.getCurrentDay() + const { month, year } = this.calendar + + const cjdn = this.computeCJDNFromModernDate(year, month, day) + const [yearValue, weekDay] = this.computeCalendarValues(cjdn) + const [ + i, + babylonianLunation, + babYear, + babMonth, + ] = this.computeBabylonianValues(cjdn) + const [j, regnalYear] = this.computeRegnalValues(i, babYear) + const babylonianDay = cjdn - data.babylonCjdnPd[i - 1] + 1 + const babylonianMonthLength = + data.babylonCjdnPd[i] - data.babylonCjdnPd[i - 1] + + this.updateDate(yearValue, month, day) + this.calendar.bcYear = yearValue < 1 ? String(1 - yearValue) : ' ' + this.calendar.julianDay = cjdn + this.calendar.weekDay = weekDay + this.calendar.babylonianDay = babylonianDay + this.calendar.babylonianMonth = babMonth + this.calendar.babylonianRuler = + babYear < 161 ? `${regnalYear} ${data.babylonRulerNames[j - 1]}` : ' ' + this.calendar.seBabylonianYear = String(babYear) + this.calendar.seMacedonianYear = babYear < 1 ? ' ' : String(babYear) + this.calendar.seMacedonianYear = + babYear > 0 && babMonth < 7 + ? String(babYear) + : babYear > -1 && babMonth > 6 + ? String(babYear + 1) + : this.calendar.seMacedonianYear + this.calendar.arsacidYear = babYear < 65 ? ' ' : String(babYear - 64) + this.calendar.babylonianLunation = babylonianLunation + this.calendar.babylonianMonthLength = babylonianMonthLength + } + + private updateDate(year: number, month: number, day: number): void { + this.calendar.year = year + this.calendar.month = month + this.calendar.day = day + } + + private computeCJDNFromModernDate( + year: number, + month: number, + day: number + ): number { + return ( + Math.floor(365.25 * (month < 3 ? year - 1 : year + 4716)) + + Math.floor(30.6001 * (month < 3 ? month + 12 : month + 1)) + + day - + 1524 + ) + } + + private computeCalendarValues(cjdn: number): [number, number] { + const b = cjdn + 1524 + const c = Math.floor((b - 122.1) / 365.25) + const year = c - 4716 + const weekDay = ((cjdn + 1) % 7) + 1 + return [year, weekDay] + } + + private computeBabylonianValues( + cjdn: number + ): [number, number, number, number] { + const i = data.babylonCjdnPd.findIndex((cjdnPd) => cjdnPd > cjdn) + const babylonianLunation = 1498 + i + const babYearMonth = data.babylonYmPd[i - 1] + const babYear = + babYearMonth < 0 ? -Math.floor(-babYearMonth) : Math.floor(babYearMonth) + const babMonth = + babYearMonth < 0 + ? Math.floor(100 * (-babYearMonth + babYear) + 0.001) + : Math.floor(100 * (babYearMonth - Math.floor(babYearMonth)) + 0.001) + return [i, babylonianLunation, babYear, babMonth] + } + + private computeRegnalValues(i: number, babYear: number): [number, number] { + const j = data.babylonRulerYears.findIndex((year) => year > babYear) + const regnalYear = babYear - data.babylonRulerYears[j - 1] + 1 + return [j, regnalYear] + } + + /* + private computeYearMonth( + day: number, + month: number, + year: number + ): [number, number] { + const cjdn = this.computeCJDNFromModernDate(year, month, day) + const [, , babYear, babMonth] = this.computeBabylonianValues(cjdn) + return [babYear, babMonth] + }*/ +} diff --git a/src/fragmentarium/domain/FragmentDtos.ts b/src/fragmentarium/domain/FragmentDtos.ts index 8df05a271..47b075628 100644 --- a/src/fragmentarium/domain/FragmentDtos.ts +++ b/src/fragmentarium/domain/FragmentDtos.ts @@ -3,6 +3,7 @@ import Folio from './Folio' import { Introduction, Notes, ScriptDto } from './fragment' import { RecordEntry } from './RecordEntry' import MuseumNumber from './MuseumNumber' +import { King } from 'common/BrinkmanKings' interface MeasureDto { value?: number @@ -14,6 +15,23 @@ export interface GenreDto { uncertain: boolean } +interface DateFieldDto { + value: string + broken?: boolean + uncertain?: boolean +} + +interface MonthFieldDto extends DateFieldDto { + intercalary?: boolean +} + +export interface MesopotamianDateDto { + era: King | string // ToDo: ADD SCHEMA + year: DateFieldDto + month: MonthFieldDto + day: DateFieldDto +} + export interface TextDto { lines: readonly any[] numberOfLines?: number @@ -67,4 +85,6 @@ export default interface FragmentDto { script: ScriptDto externalNumbers: ExternalNumbers projects: readonly string[] + date?: MesopotamianDateDto + datesInText?: readonly MesopotamianDateDto[] } diff --git a/src/fragmentarium/domain/dateConverterData.json b/src/fragmentarium/domain/dateConverterData.json new file mode 100644 index 000000000..c209c92fd --- /dev/null +++ b/src/fragmentarium/domain/dateConverterData.json @@ -0,0 +1,17444 @@ +{ + "babylonRulerNames": [ + "Nabonassar", + "Nabu-nadin-zeri", + "Nabu-mukin-zeri", + "Tiglath-Pileser III [Pulu]", + "Salmanassar V [Ululayu]", + "Marduk-apal-iddina", + "Sargon II", + "Sennacherib", + "Bel-ibni", + "Aššur-nadim-šum", + "Nergal-ušezib", + "Mušezib-Marduk", + "Sennacherib", + "Asarhaddon", + "Šamaš-šum-ukin", + "Kandalānu", + "Interregnum", + "Nabopolassar", + "Nebuchadnezzar II", + "Amēl-Marduk", + "Nergal-šar-usur", + "Nabunaid", + "Cyrus", + "Cambyses", + "Darius I", + "Xerxes", + "Artaxerxes I", + "Darius II", + "Artaxerxes II Memnon", + "Artaxerxes III Ochus", + "Artaxerxes IV Arses", + "Darius III", + "Alexander III [the Great]", + "Philip III Arrhidaeus", + "Alexander IV Aegus", + "Seleucus I Nicator", + "Antiochus I Soter", + "Antiochus II Theos", + "Seleucus II Callinicus", + "Seleucus III Soter", + "Antiochus III [the Great]", + "Seleucus IV Philopater", + "Antiochus IV Epiphanes", + "Antiochus V Eupator", + "Demetrius I Soter", + "Alexander Balas" + ], + "babylonRulerYears": [ + -436, + -422, + -420, + -417, + -415, + -410, + -398, + -393, + -391, + -388, + -382, + -381, + -377, + -369, + -356, + -336, + -314, + -313, + -292, + -249, + -247, + -243, + -226, + -217, + -209, + -173, + -152, + -111, + -92, + -46, + -25, + -23, + -18, + -10, + -3, + 1, + 31, + 51, + 66, + 87, + 90, + 125, + 137, + 148, + 150, + 162 + ], + + "babylonCjdnPd": [ + 1492871, + 1492901, + 1492931, + 1492960, + 1492990, + 1493019, + 1493048, + 1493078, + 1493107, + 1493137, + 1493166, + 1493196, + 1493225, + 1493255, + 1493285, + 1493314, + 1493344, + 1493373, + 1493403, + 1493433, + 1493462, + 1493492, + 1493521, + 1493550, + 1493580, + 1493609, + 1493639, + 1493668, + 1493698, + 1493728, + 1493757, + 1493787, + 1493817, + 1493846, + 1493876, + 1493905, + 1493934, + 1493964, + 1493993, + 1494023, + 1494052, + 1494082, + 1494111, + 1494141, + 1494171, + 1494201, + 1494230, + 1494260, + 1494289, + 1494318, + 1494348, + 1494377, + 1494406, + 1494436, + 1494465, + 1494495, + 1494525, + 1494555, + 1494584, + 1494614, + 1494644, + 1494673, + 1494702, + 1494732, + 1494761, + 1494790, + 1494820, + 1494849, + 1494879, + 1494909, + 1494939, + 1494969, + 1494998, + 1495028, + 1495057, + 1495086, + 1495116, + 1495145, + 1495174, + 1495204, + 1495233, + 1495263, + 1495293, + 1495323, + 1495352, + 1495382, + 1495411, + 1495441, + 1495470, + 1495500, + 1495529, + 1495558, + 1495588, + 1495618, + 1495647, + 1495677, + 1495706, + 1495736, + 1495765, + 1495795, + 1495825, + 1495854, + 1495884, + 1495913, + 1495942, + 1495972, + 1496002, + 1496031, + 1496060, + 1496090, + 1496119, + 1496149, + 1496179, + 1496208, + 1496238, + 1496268, + 1496297, + 1496327, + 1496356, + 1496386, + 1496415, + 1496444, + 1496474, + 1496503, + 1496533, + 1496562, + 1496592, + 1496622, + 1496652, + 1496681, + 1496711, + 1496740, + 1496770, + 1496799, + 1496828, + 1496858, + 1496887, + 1496917, + 1496946, + 1496976, + 1497006, + 1497036, + 1497065, + 1497095, + 1497124, + 1497154, + 1497183, + 1497212, + 1497242, + 1497271, + 1497300, + 1497330, + 1497360, + 1497390, + 1497420, + 1497449, + 1497479, + 1497508, + 1497537, + 1497567, + 1497596, + 1497626, + 1497655, + 1497684, + 1497714, + 1497744, + 1497773, + 1497803, + 1497833, + 1497862, + 1497892, + 1497921, + 1497951, + 1497980, + 1498010, + 1498039, + 1498068, + 1498098, + 1498128, + 1498157, + 1498187, + 1498216, + 1498246, + 1498276, + 1498305, + 1498335, + 1498364, + 1498394, + 1498423, + 1498452, + 1498482, + 1498511, + 1498541, + 1498570, + 1498600, + 1498630, + 1498660, + 1498689, + 1498719, + 1498748, + 1498778, + 1498807, + 1498837, + 1498866, + 1498895, + 1498925, + 1498954, + 1498984, + 1499014, + 1499043, + 1499073, + 1499103, + 1499132, + 1499162, + 1499191, + 1499221, + 1499250, + 1499279, + 1499309, + 1499338, + 1499368, + 1499397, + 1499427, + 1499457, + 1499486, + 1499516, + 1499546, + 1499575, + 1499604, + 1499634, + 1499663, + 1499693, + 1499722, + 1499752, + 1499781, + 1499811, + 1499840, + 1499870, + 1499900, + 1499929, + 1499959, + 1499988, + 1500018, + 1500047, + 1500077, + 1500106, + 1500136, + 1500165, + 1500195, + 1500224, + 1500254, + 1500283, + 1500313, + 1500343, + 1500372, + 1500402, + 1500432, + 1500461, + 1500490, + 1500520, + 1500549, + 1500578, + 1500608, + 1500637, + 1500667, + 1500697, + 1500727, + 1500756, + 1500786, + 1500816, + 1500845, + 1500874, + 1500904, + 1500933, + 1500962, + 1500992, + 1501021, + 1501051, + 1501081, + 1501110, + 1501140, + 1501170, + 1501200, + 1501229, + 1501258, + 1501288, + 1501317, + 1501346, + 1501375, + 1501405, + 1501435, + 1501465, + 1501494, + 1501524, + 1501554, + 1501583, + 1501613, + 1501642, + 1501672, + 1501701, + 1501730, + 1501760, + 1501789, + 1501819, + 1501849, + 1501878, + 1501908, + 1501937, + 1501967, + 1501997, + 1502026, + 1502056, + 1502085, + 1502114, + 1502144, + 1502173, + 1502203, + 1502233, + 1502262, + 1502292, + 1502321, + 1502351, + 1502380, + 1502410, + 1502439, + 1502469, + 1502498, + 1502528, + 1502556, + 1502586, + 1502616, + 1502646, + 1502675, + 1502704, + 1502734, + 1502764, + 1502794, + 1502823, + 1502853, + 1502883, + 1502912, + 1502942, + 1502971, + 1503000, + 1503030, + 1503059, + 1503089, + 1503118, + 1503148, + 1503177, + 1503207, + 1503237, + 1503267, + 1503296, + 1503326, + 1503355, + 1503384, + 1503414, + 1503443, + 1503472, + 1503502, + 1503531, + 1503561, + 1503591, + 1503621, + 1503651, + 1503680, + 1503709, + 1503739, + 1503768, + 1503798, + 1503827, + 1503856, + 1503886, + 1503915, + 1503945, + 1503975, + 1504005, + 1504035, + 1504064, + 1504093, + 1504123, + 1504152, + 1504182, + 1504211, + 1504240, + 1504270, + 1504299, + 1504329, + 1504359, + 1504388, + 1504418, + 1504448, + 1504477, + 1504507, + 1504536, + 1504566, + 1504595, + 1504624, + 1504654, + 1504683, + 1504713, + 1504743, + 1504772, + 1504802, + 1504831, + 1504861, + 1504891, + 1504920, + 1504950, + 1504979, + 1505008, + 1505038, + 1505067, + 1505097, + 1505126, + 1505156, + 1505185, + 1505215, + 1505245, + 1505275, + 1505304, + 1505334, + 1505363, + 1505393, + 1505422, + 1505451, + 1505481, + 1505510, + 1505539, + 1505569, + 1505599, + 1505629, + 1505658, + 1505688, + 1505718, + 1505747, + 1505777, + 1505806, + 1505835, + 1505865, + 1505894, + 1505923, + 1505953, + 1505983, + 1506012, + 1506042, + 1506072, + 1506101, + 1506131, + 1506160, + 1506190, + 1506219, + 1506249, + 1506278, + 1506308, + 1506337, + 1506366, + 1506396, + 1506426, + 1506455, + 1506485, + 1506514, + 1506544, + 1506574, + 1506603, + 1506633, + 1506662, + 1506692, + 1506721, + 1506750, + 1506780, + 1506809, + 1506839, + 1506868, + 1506898, + 1506928, + 1506958, + 1506987, + 1507017, + 1507046, + 1507076, + 1507105, + 1507134, + 1507164, + 1507193, + 1507223, + 1507252, + 1507282, + 1507312, + 1507342, + 1507371, + 1507401, + 1507430, + 1507460, + 1507489, + 1507518, + 1507548, + 1507577, + 1507606, + 1507636, + 1507666, + 1507696, + 1507726, + 1507755, + 1507785, + 1507814, + 1507844, + 1507873, + 1507902, + 1507932, + 1507961, + 1507990, + 1508020, + 1508050, + 1508080, + 1508109, + 1508139, + 1508169, + 1508198, + 1508228, + 1508257, + 1508286, + 1508316, + 1508345, + 1508374, + 1508404, + 1508434, + 1508464, + 1508493, + 1508523, + 1508552, + 1508582, + 1508611, + 1508641, + 1508670, + 1508700, + 1508729, + 1508759, + 1508788, + 1508818, + 1508847, + 1508877, + 1508906, + 1508936, + 1508966, + 1508995, + 1509025, + 1509054, + 1509084, + 1509113, + 1509143, + 1509172, + 1509202, + 1509231, + 1509261, + 1509290, + 1509320, + 1509349, + 1509379, + 1509409, + 1509438, + 1509468, + 1509498, + 1509527, + 1509556, + 1509586, + 1509615, + 1509644, + 1509674, + 1509703, + 1509733, + 1509763, + 1509793, + 1509822, + 1509852, + 1509882, + 1509911, + 1509940, + 1509970, + 1509999, + 1510028, + 1510058, + 1510087, + 1510117, + 1510147, + 1510177, + 1510206, + 1510236, + 1510266, + 1510295, + 1510324, + 1510354, + 1510383, + 1510412, + 1510442, + 1510471, + 1510501, + 1510530, + 1510560, + 1510590, + 1510620, + 1510649, + 1510679, + 1510708, + 1510738, + 1510767, + 1510796, + 1510826, + 1510855, + 1510885, + 1510914, + 1510944, + 1510974, + 1511003, + 1511033, + 1511063, + 1511092, + 1511122, + 1511151, + 1511180, + 1511210, + 1511239, + 1511269, + 1511298, + 1511328, + 1511357, + 1511387, + 1511417, + 1511446, + 1511476, + 1511506, + 1511535, + 1511564, + 1511594, + 1511623, + 1511653, + 1511682, + 1511712, + 1511741, + 1511771, + 1511800, + 1511830, + 1511860, + 1511889, + 1511919, + 1511948, + 1511978, + 1512007, + 1512037, + 1512066, + 1512095, + 1512125, + 1512154, + 1512184, + 1512214, + 1512244, + 1512273, + 1512303, + 1512332, + 1512362, + 1512391, + 1512421, + 1512450, + 1512479, + 1512509, + 1512538, + 1512568, + 1512598, + 1512627, + 1512657, + 1512687, + 1512716, + 1512746, + 1512775, + 1512805, + 1512834, + 1512863, + 1512893, + 1512922, + 1512952, + 1512981, + 1513011, + 1513041, + 1513070, + 1513100, + 1513130, + 1513159, + 1513189, + 1513218, + 1513248, + 1513277, + 1513306, + 1513336, + 1513365, + 1513395, + 1513424, + 1513454, + 1513483, + 1513513, + 1513543, + 1513573, + 1513602, + 1513632, + 1513661, + 1513690, + 1513720, + 1513749, + 1513778, + 1513808, + 1513838, + 1513867, + 1513897, + 1513927, + 1513957, + 1513986, + 1514016, + 1514045, + 1514074, + 1514104, + 1514133, + 1514162, + 1514192, + 1514221, + 1514251, + 1514281, + 1514311, + 1514341, + 1514370, + 1514400, + 1514429, + 1514458, + 1514488, + 1514517, + 1514546, + 1514576, + 1514605, + 1514635, + 1514665, + 1514695, + 1514724, + 1514754, + 1514783, + 1514813, + 1514842, + 1514871, + 1514901, + 1514930, + 1514960, + 1514989, + 1515019, + 1515049, + 1515078, + 1515108, + 1515138, + 1515167, + 1515197, + 1515226, + 1515255, + 1515285, + 1515314, + 1515344, + 1515374, + 1515403, + 1515433, + 1515462, + 1515492, + 1515521, + 1515551, + 1515580, + 1515610, + 1515639, + 1515669, + 1515699, + 1515728, + 1515758, + 1515787, + 1515816, + 1515846, + 1515875, + 1515905, + 1515935, + 1515964, + 1515994, + 1516024, + 1516053, + 1516083, + 1516112, + 1516142, + 1516171, + 1516200, + 1516230, + 1516259, + 1516289, + 1516318, + 1516348, + 1516378, + 1516408, + 1516438, + 1516467, + 1516496, + 1516526, + 1516555, + 1516584, + 1516614, + 1516643, + 1516672, + 1516702, + 1516732, + 1516762, + 1516792, + 1516821, + 1516851, + 1516880, + 1516910, + 1516939, + 1516968, + 1516997, + 1517027, + 1517056, + 1517086, + 1517116, + 1517146, + 1517176, + 1517205, + 1517235, + 1517264, + 1517294, + 1517323, + 1517352, + 1517382, + 1517411, + 1517440, + 1517470, + 1517500, + 1517530, + 1517559, + 1517589, + 1517618, + 1517648, + 1517677, + 1517707, + 1517736, + 1517766, + 1517795, + 1517825, + 1517854, + 1517884, + 1517913, + 1517943, + 1517972, + 1518002, + 1518032, + 1518061, + 1518091, + 1518120, + 1518150, + 1518179, + 1518209, + 1518238, + 1518267, + 1518297, + 1518326, + 1518356, + 1518386, + 1518415, + 1518445, + 1518475, + 1518504, + 1518534, + 1518563, + 1518593, + 1518622, + 1518651, + 1518681, + 1518710, + 1518739, + 1518769, + 1518799, + 1518829, + 1518859, + 1518888, + 1518918, + 1518947, + 1518977, + 1519006, + 1519035, + 1519065, + 1519094, + 1519124, + 1519153, + 1519183, + 1519213, + 1519242, + 1519272, + 1519301, + 1519331, + 1519361, + 1519390, + 1519419, + 1519449, + 1519478, + 1519508, + 1519537, + 1519567, + 1519596, + 1519626, + 1519655, + 1519685, + 1519715, + 1519744, + 1519774, + 1519803, + 1519833, + 1519862, + 1519892, + 1519921, + 1519950, + 1519980, + 1520009, + 1520039, + 1520069, + 1520099, + 1520128, + 1520158, + 1520188, + 1520217, + 1520246, + 1520276, + 1520305, + 1520334, + 1520364, + 1520393, + 1520423, + 1520453, + 1520482, + 1520512, + 1520542, + 1520572, + 1520601, + 1520630, + 1520660, + 1520689, + 1520718, + 1520748, + 1520777, + 1520807, + 1520837, + 1520866, + 1520896, + 1520926, + 1520955, + 1520985, + 1521014, + 1521044, + 1521073, + 1521102, + 1521132, + 1521161, + 1521191, + 1521221, + 1521250, + 1521280, + 1521310, + 1521339, + 1521369, + 1521398, + 1521428, + 1521457, + 1521486, + 1521516, + 1521545, + 1521575, + 1521605, + 1521634, + 1521664, + 1521693, + 1521723, + 1521753, + 1521782, + 1521811, + 1521841, + 1521870, + 1521900, + 1521929, + 1521959, + 1521988, + 1522018, + 1522047, + 1522077, + 1522107, + 1522136, + 1522166, + 1522195, + 1522225, + 1522254, + 1522284, + 1522314, + 1522343, + 1522372, + 1522402, + 1522431, + 1522461, + 1522490, + 1522520, + 1522549, + 1522579, + 1522609, + 1522638, + 1522668, + 1522698, + 1522727, + 1522756, + 1522786, + 1522815, + 1522844, + 1522874, + 1522903, + 1522933, + 1522963, + 1522993, + 1523023, + 1523052, + 1523082, + 1523111, + 1523140, + 1523170, + 1523199, + 1523228, + 1523258, + 1523287, + 1523317, + 1523347, + 1523377, + 1523407, + 1523436, + 1523466, + 1523495, + 1523524, + 1523553, + 1523583, + 1523612, + 1523642, + 1523671, + 1523701, + 1523731, + 1523760, + 1523790, + 1523820, + 1523849, + 1523879, + 1523908, + 1523938, + 1523967, + 1523996, + 1524026, + 1524055, + 1524085, + 1524114, + 1524144, + 1524174, + 1524204, + 1524233, + 1524263, + 1524292, + 1524322, + 1524351, + 1524380, + 1524410, + 1524439, + 1524469, + 1524499, + 1524528, + 1524558, + 1524587, + 1524617, + 1524647, + 1524676, + 1524706, + 1524735, + 1524765, + 1524794, + 1524823, + 1524853, + 1524882, + 1524911, + 1524941, + 1524971, + 1525001, + 1525030, + 1525060, + 1525089, + 1525119, + 1525149, + 1525178, + 1525207, + 1525237, + 1525266, + 1525296, + 1525325, + 1525355, + 1525384, + 1525414, + 1525444, + 1525473, + 1525503, + 1525533, + 1525562, + 1525591, + 1525621, + 1525650, + 1525679, + 1525709, + 1525739, + 1525768, + 1525798, + 1525828, + 1525857, + 1525887, + 1525917, + 1525946, + 1525975, + 1526005, + 1526034, + 1526064, + 1526093, + 1526122, + 1526152, + 1526182, + 1526211, + 1526241, + 1526271, + 1526300, + 1526330, + 1526359, + 1526388, + 1526418, + 1526447, + 1526477, + 1526506, + 1526536, + 1526566, + 1526595, + 1526625, + 1526654, + 1526684, + 1526714, + 1526743, + 1526773, + 1526802, + 1526832, + 1526861, + 1526890, + 1526920, + 1526950, + 1526979, + 1527008, + 1527038, + 1527068, + 1527098, + 1527127, + 1527157, + 1527186, + 1527216, + 1527245, + 1527274, + 1527304, + 1527333, + 1527362, + 1527392, + 1527422, + 1527452, + 1527481, + 1527511, + 1527541, + 1527570, + 1527600, + 1527629, + 1527658, + 1527687, + 1527717, + 1527746, + 1527776, + 1527806, + 1527836, + 1527865, + 1527894, + 1527925, + 1527954, + 1527984, + 1528013, + 1528042, + 1528072, + 1528101, + 1528131, + 1528160, + 1528190, + 1528219, + 1528249, + 1528279, + 1528308, + 1528338, + 1528367, + 1528397, + 1528426, + 1528456, + 1528485, + 1528515, + 1528544, + 1528574, + 1528603, + 1528633, + 1528662, + 1528692, + 1528721, + 1528751, + 1528781, + 1528810, + 1528840, + 1528870, + 1528899, + 1528928, + 1528958, + 1528987, + 1529016, + 1529046, + 1529075, + 1529105, + 1529135, + 1529164, + 1529194, + 1529224, + 1529254, + 1529283, + 1529312, + 1529342, + 1529371, + 1529400, + 1529430, + 1529459, + 1529489, + 1529519, + 1529549, + 1529579, + 1529608, + 1529637, + 1529667, + 1529696, + 1529726, + 1529755, + 1529784, + 1529813, + 1529843, + 1529873, + 1529903, + 1529933, + 1529962, + 1529992, + 1530021, + 1530051, + 1530080, + 1530110, + 1530139, + 1530168, + 1530197, + 1530227, + 1530257, + 1530287, + 1530316, + 1530346, + 1530376, + 1530405, + 1530435, + 1530464, + 1530494, + 1530523, + 1530552, + 1530582, + 1530611, + 1530641, + 1530671, + 1530700, + 1530730, + 1530759, + 1530789, + 1530819, + 1530848, + 1530877, + 1530907, + 1530936, + 1530966, + 1530995, + 1531025, + 1531054, + 1531084, + 1531113, + 1531143, + 1531173, + 1531202, + 1531232, + 1531261, + 1531291, + 1531320, + 1531350, + 1531379, + 1531409, + 1531438, + 1531468, + 1531497, + 1531527, + 1531556, + 1531586, + 1531616, + 1531645, + 1531675, + 1531705, + 1531734, + 1531763, + 1531793, + 1531822, + 1531851, + 1531881, + 1531910, + 1531940, + 1531970, + 1531999, + 1532029, + 1532059, + 1532089, + 1532118, + 1532147, + 1532177, + 1532206, + 1532235, + 1532265, + 1532294, + 1532324, + 1532353, + 1532383, + 1532413, + 1532443, + 1532472, + 1532502, + 1532531, + 1532561, + 1532590, + 1532619, + 1532649, + 1532678, + 1532708, + 1532737, + 1532767, + 1532797, + 1532826, + 1532856, + 1532886, + 1532915, + 1532945, + 1532974, + 1533004, + 1533033, + 1533062, + 1533092, + 1533121, + 1533151, + 1533180, + 1533210, + 1533240, + 1533269, + 1533299, + 1533329, + 1533358, + 1533388, + 1533417, + 1533446, + 1533476, + 1533505, + 1533534, + 1533564, + 1533594, + 1533623, + 1533653, + 1533683, + 1533713, + 1533742, + 1533772, + 1533801, + 1533830, + 1533860, + 1533889, + 1533918, + 1533948, + 1533977, + 1534007, + 1534037, + 1534067, + 1534096, + 1534126, + 1534156, + 1534185, + 1534214, + 1534244, + 1534273, + 1534303, + 1534332, + 1534361, + 1534391, + 1534421, + 1534451, + 1534480, + 1534510, + 1534539, + 1534569, + 1534598, + 1534627, + 1534657, + 1534687, + 1534716, + 1534747, + 1534776, + 1534805, + 1534834, + 1534864, + 1534893, + 1534923, + 1534953, + 1534982, + 1535011, + 1535041, + 1535071, + 1535100, + 1535130, + 1535159, + 1535188, + 1535218, + 1535248, + 1535277, + 1535307, + 1535336, + 1535366, + 1535396, + 1535425, + 1535455, + 1535484, + 1535514, + 1535543, + 1535572, + 1535602, + 1535631, + 1535661, + 1535690, + 1535720, + 1535750, + 1535780, + 1535809, + 1535839, + 1535868, + 1535898, + 1535927, + 1535956, + 1535986, + 1536015, + 1536044, + 1536074, + 1536104, + 1536134, + 1536164, + 1536194, + 1536223, + 1536252, + 1536282, + 1536311, + 1536340, + 1536369, + 1536399, + 1536428, + 1536458, + 1536488, + 1536518, + 1536548, + 1536577, + 1536607, + 1536636, + 1536666, + 1536695, + 1536724, + 1536753, + 1536783, + 1536812, + 1536842, + 1536872, + 1536902, + 1536931, + 1536961, + 1536991, + 1537020, + 1537049, + 1537079, + 1537108, + 1537137, + 1537167, + 1537196, + 1537226, + 1537256, + 1537285, + 1537315, + 1537345, + 1537374, + 1537404, + 1537433, + 1537463, + 1537492, + 1537522, + 1537551, + 1537581, + 1537610, + 1537640, + 1537669, + 1537699, + 1537728, + 1537758, + 1537788, + 1537817, + 1537847, + 1537876, + 1537906, + 1537935, + 1537965, + 1537994, + 1538024, + 1538053, + 1538082, + 1538112, + 1538142, + 1538171, + 1538201, + 1538231, + 1538260, + 1538290, + 1538319, + 1538349, + 1538378, + 1538407, + 1538437, + 1538466, + 1538496, + 1538525, + 1538555, + 1538585, + 1538614, + 1538644, + 1538674, + 1538703, + 1538733, + 1538762, + 1538791, + 1538821, + 1538850, + 1538880, + 1538909, + 1538939, + 1538968, + 1538998, + 1539028, + 1539058, + 1539087, + 1539117, + 1539146, + 1539175, + 1539205, + 1539234, + 1539264, + 1539293, + 1539323, + 1539352, + 1539382, + 1539412, + 1539441, + 1539471, + 1539500, + 1539530, + 1539559, + 1539589, + 1539618, + 1539648, + 1539677, + 1539706, + 1539736, + 1539766, + 1539795, + 1539825, + 1539855, + 1539884, + 1539914, + 1539944, + 1539973, + 1540002, + 1540032, + 1540061, + 1540090, + 1540120, + 1540149, + 1540179, + 1540209, + 1540238, + 1540268, + 1540298, + 1540327, + 1540357, + 1540386, + 1540416, + 1540445, + 1540474, + 1540504, + 1540533, + 1540563, + 1540592, + 1540622, + 1540652, + 1540681, + 1540711, + 1540741, + 1540770, + 1540800, + 1540829, + 1540858, + 1540888, + 1540917, + 1540947, + 1540976, + 1541006, + 1541036, + 1541065, + 1541095, + 1541125, + 1541154, + 1541184, + 1541213, + 1541242, + 1541272, + 1541301, + 1541331, + 1541360, + 1541390, + 1541420, + 1541449, + 1541479, + 1541508, + 1541538, + 1541567, + 1541597, + 1541626, + 1541656, + 1541685, + 1541715, + 1541744, + 1541774, + 1541803, + 1541833, + 1541862, + 1541892, + 1541922, + 1541951, + 1541981, + 1542011, + 1542040, + 1542070, + 1542099, + 1542128, + 1542158, + 1542187, + 1542217, + 1542246, + 1542276, + 1542305, + 1542335, + 1542365, + 1542395, + 1542424, + 1542454, + 1542483, + 1542512, + 1542542, + 1542571, + 1542600, + 1542630, + 1542659, + 1542689, + 1542719, + 1542749, + 1542779, + 1542808, + 1542838, + 1542867, + 1542896, + 1542925, + 1542955, + 1542984, + 1543014, + 1543043, + 1543073, + 1543103, + 1543133, + 1543163, + 1543192, + 1543221, + 1543251, + 1543280, + 1543309, + 1543339, + 1543368, + 1543398, + 1543427, + 1543457, + 1543487, + 1543517, + 1543546, + 1543576, + 1543605, + 1543635, + 1543664, + 1543694, + 1543723, + 1543752, + 1543782, + 1543812, + 1543841, + 1543871, + 1543900, + 1543930, + 1543959, + 1543989, + 1544019, + 1544048, + 1544077, + 1544107, + 1544136, + 1544166, + 1544196, + 1544225, + 1544254, + 1544284, + 1544313, + 1544343, + 1544373, + 1544402, + 1544432, + 1544462, + 1544491, + 1544521, + 1544550, + 1544580, + 1544609, + 1544638, + 1544668, + 1544697, + 1544727, + 1544757, + 1544786, + 1544816, + 1544846, + 1544875, + 1544905, + 1544934, + 1544963, + 1544993, + 1545022, + 1545051, + 1545081, + 1545111, + 1545140, + 1545170, + 1545200, + 1545230, + 1545259, + 1545289, + 1545318, + 1545347, + 1545377, + 1545406, + 1545435, + 1545465, + 1545494, + 1545524, + 1545554, + 1545584, + 1545613, + 1545643, + 1545673, + 1545702, + 1545731, + 1545761, + 1545790, + 1545819, + 1545849, + 1545878, + 1545908, + 1545938, + 1545967, + 1545997, + 1546027, + 1546056, + 1546086, + 1546115, + 1546145, + 1546174, + 1546204, + 1546233, + 1546262, + 1546292, + 1546321, + 1546351, + 1546381, + 1546410, + 1546440, + 1546470, + 1546499, + 1546529, + 1546558, + 1546588, + 1546617, + 1546646, + 1546676, + 1546705, + 1546735, + 1546764, + 1546794, + 1546824, + 1546854, + 1546883, + 1546913, + 1546942, + 1546972, + 1547001, + 1547030, + 1547060, + 1547089, + 1547118, + 1547148, + 1547178, + 1547208, + 1547237, + 1547267, + 1547297, + 1547326, + 1547356, + 1547385, + 1547414, + 1547444, + 1547473, + 1547502, + 1547532, + 1547562, + 1547591, + 1547621, + 1547651, + 1547680, + 1547710, + 1547739, + 1547769, + 1547798, + 1547828, + 1547857, + 1547887, + 1547916, + 1547946, + 1547975, + 1548005, + 1548034, + 1548064, + 1548094, + 1548123, + 1548153, + 1548182, + 1548212, + 1548241, + 1548271, + 1548300, + 1548330, + 1548359, + 1548389, + 1548418, + 1548448, + 1548477, + 1548507, + 1548537, + 1548566, + 1548596, + 1548626, + 1548655, + 1548684, + 1548714, + 1548743, + 1548772, + 1548802, + 1548831, + 1548861, + 1548891, + 1548921, + 1548950, + 1548980, + 1549010, + 1549039, + 1549068, + 1549097, + 1549127, + 1549156, + 1549186, + 1549216, + 1549246, + 1549275, + 1549305, + 1549334, + 1549364, + 1549394, + 1549423, + 1549452, + 1549481, + 1549511, + 1549540, + 1549569, + 1549599, + 1549629, + 1549659, + 1549689, + 1549718, + 1549748, + 1549777, + 1549807, + 1549836, + 1549866, + 1549895, + 1549924, + 1549953, + 1549983, + 1550013, + 1550043, + 1550072, + 1550102, + 1550132, + 1550161, + 1550191, + 1550220, + 1550249, + 1550279, + 1550308, + 1550338, + 1550367, + 1550397, + 1550426, + 1550456, + 1550486, + 1550515, + 1550545, + 1550574, + 1550604, + 1550633, + 1550663, + 1550692, + 1550722, + 1550751, + 1550781, + 1550810, + 1550840, + 1550869, + 1550899, + 1550928, + 1550958, + 1550988, + 1551017, + 1551047, + 1551077, + 1551106, + 1551136, + 1551165, + 1551194, + 1551223, + 1551253, + 1551282, + 1551312, + 1551342, + 1551371, + 1551401, + 1551431, + 1551461, + 1551490, + 1551520, + 1551549, + 1551578, + 1551607, + 1551637, + 1551666, + 1551696, + 1551726, + 1551755, + 1551785, + 1551815, + 1551845, + 1551874, + 1551903, + 1551933, + 1551962, + 1551991, + 1552021, + 1552050, + 1552080, + 1552109, + 1552139, + 1552169, + 1552199, + 1552228, + 1552258, + 1552287, + 1552317, + 1552346, + 1552375, + 1552405, + 1552434, + 1552464, + 1552493, + 1552523, + 1552553, + 1552582, + 1552612, + 1552642, + 1552671, + 1552701, + 1552730, + 1552760, + 1552789, + 1552818, + 1552848, + 1552877, + 1552907, + 1552936, + 1552966, + 1552996, + 1553025, + 1553055, + 1553085, + 1553114, + 1553144, + 1553173, + 1553202, + 1553232, + 1553261, + 1553291, + 1553320, + 1553350, + 1553379, + 1553409, + 1553439, + 1553468, + 1553498, + 1553528, + 1553557, + 1553586, + 1553616, + 1553645, + 1553674, + 1553704, + 1553733, + 1553763, + 1553793, + 1553823, + 1553852, + 1553882, + 1553911, + 1553941, + 1553970, + 1554000, + 1554029, + 1554058, + 1554088, + 1554117, + 1554147, + 1554177, + 1554206, + 1554236, + 1554266, + 1554295, + 1554325, + 1554354, + 1554384, + 1554413, + 1554442, + 1554472, + 1554501, + 1554531, + 1554561, + 1554590, + 1554620, + 1554649, + 1554679, + 1554709, + 1554738, + 1554768, + 1554797, + 1554827, + 1554856, + 1554886, + 1554915, + 1554944, + 1554974, + 1555003, + 1555033, + 1555063, + 1555092, + 1555122, + 1555152, + 1555181, + 1555211, + 1555240, + 1555270, + 1555299, + 1555328, + 1555358, + 1555387, + 1555417, + 1555446, + 1555476, + 1555506, + 1555536, + 1555565, + 1555595, + 1555624, + 1555654, + 1555683, + 1555712, + 1555741, + 1555771, + 1555800, + 1555830, + 1555860, + 1555890, + 1555920, + 1555949, + 1555979, + 1556008, + 1556038, + 1556067, + 1556096, + 1556125, + 1556155, + 1556184, + 1556214, + 1556244, + 1556274, + 1556304, + 1556333, + 1556363, + 1556392, + 1556422, + 1556451, + 1556480, + 1556509, + 1556539, + 1556568, + 1556598, + 1556628, + 1556658, + 1556687, + 1556717, + 1556746, + 1556776, + 1556805, + 1556835, + 1556864, + 1556893, + 1556923, + 1556953, + 1556982, + 1557012, + 1557041, + 1557071, + 1557100, + 1557130, + 1557160, + 1557189, + 1557219, + 1557248, + 1557278, + 1557307, + 1557337, + 1557366, + 1557395, + 1557425, + 1557454, + 1557484, + 1557514, + 1557543, + 1557573, + 1557603, + 1557632, + 1557662, + 1557691, + 1557721, + 1557750, + 1557779, + 1557809, + 1557838, + 1557868, + 1557897, + 1557927, + 1557957, + 1557987, + 1558016, + 1558046, + 1558076, + 1558105, + 1558134, + 1558163, + 1558193, + 1558222, + 1558252, + 1558281, + 1558311, + 1558341, + 1558370, + 1558400, + 1558430, + 1558459, + 1558489, + 1558518, + 1558547, + 1558577, + 1558606, + 1558636, + 1558665, + 1558695, + 1558724, + 1558754, + 1558784, + 1558814, + 1558843, + 1558873, + 1558902, + 1558931, + 1558961, + 1558990, + 1559019, + 1559049, + 1559079, + 1559108, + 1559138, + 1559168, + 1559197, + 1559227, + 1559256, + 1559286, + 1559315, + 1559345, + 1559374, + 1559404, + 1559433, + 1559463, + 1559492, + 1559522, + 1559551, + 1559581, + 1559611, + 1559640, + 1559670, + 1559699, + 1559729, + 1559758, + 1559788, + 1559817, + 1559846, + 1559876, + 1559905, + 1559935, + 1559965, + 1559994, + 1560024, + 1560054, + 1560083, + 1560113, + 1560142, + 1560172, + 1560201, + 1560230, + 1560260, + 1560289, + 1560319, + 1560348, + 1560378, + 1560408, + 1560438, + 1560467, + 1560497, + 1560526, + 1560556, + 1560585, + 1560614, + 1560644, + 1560673, + 1560703, + 1560732, + 1560762, + 1560791, + 1560821, + 1560851, + 1560881, + 1560910, + 1560940, + 1560969, + 1560998, + 1561028, + 1561057, + 1561087, + 1561116, + 1561146, + 1561175, + 1561205, + 1561235, + 1561264, + 1561294, + 1561323, + 1561353, + 1561382, + 1561412, + 1561441, + 1561471, + 1561500, + 1561530, + 1561559, + 1561589, + 1561618, + 1561648, + 1561678, + 1561707, + 1561737, + 1561767, + 1561796, + 1561826, + 1561855, + 1561884, + 1561913, + 1561943, + 1561972, + 1562002, + 1562032, + 1562061, + 1562091, + 1562121, + 1562151, + 1562180, + 1562210, + 1562239, + 1562268, + 1562297, + 1562327, + 1562356, + 1562386, + 1562415, + 1562445, + 1562475, + 1562505, + 1562535, + 1562564, + 1562594, + 1562623, + 1562652, + 1562681, + 1562711, + 1562740, + 1562770, + 1562799, + 1562829, + 1562859, + 1562889, + 1562918, + 1562948, + 1562977, + 1563007, + 1563036, + 1563065, + 1563095, + 1563124, + 1563154, + 1563183, + 1563213, + 1563243, + 1563272, + 1563302, + 1563332, + 1563361, + 1563391, + 1563420, + 1563449, + 1563479, + 1563508, + 1563538, + 1563568, + 1563597, + 1563627, + 1563656, + 1563686, + 1563715, + 1563745, + 1563774, + 1563804, + 1563833, + 1563863, + 1563893, + 1563922, + 1563952, + 1563981, + 1564010, + 1564040, + 1564069, + 1564099, + 1564129, + 1564158, + 1564188, + 1564218, + 1564247, + 1564277, + 1564306, + 1564336, + 1564365, + 1564394, + 1564424, + 1564453, + 1564483, + 1564512, + 1564542, + 1564572, + 1564602, + 1564631, + 1564661, + 1564690, + 1564719, + 1564749, + 1564778, + 1564807, + 1564837, + 1564866, + 1564896, + 1564926, + 1564956, + 1564986, + 1565015, + 1565045, + 1565074, + 1565103, + 1565133, + 1565162, + 1565191, + 1565221, + 1565250, + 1565280, + 1565310, + 1565340, + 1565369, + 1565399, + 1565429, + 1565458, + 1565487, + 1565517, + 1565546, + 1565575, + 1565605, + 1565634, + 1565664, + 1565694, + 1565724, + 1565753, + 1565783, + 1565812, + 1565842, + 1565871, + 1565901, + 1565930, + 1565959, + 1565989, + 1566018, + 1566048, + 1566077, + 1566107, + 1566137, + 1566166, + 1566196, + 1566226, + 1566255, + 1566285, + 1566314, + 1566344, + 1566373, + 1566402, + 1566432, + 1566461, + 1566491, + 1566520, + 1566550, + 1566580, + 1566609, + 1566639, + 1566669, + 1566698, + 1566728, + 1566757, + 1566786, + 1566816, + 1566845, + 1566875, + 1566904, + 1566934, + 1566963, + 1566993, + 1567023, + 1567053, + 1567082, + 1567112, + 1567141, + 1567170, + 1567200, + 1567229, + 1567259, + 1567288, + 1567318, + 1567347, + 1567377, + 1567407, + 1567436, + 1567466, + 1567496, + 1567525, + 1567554, + 1567584, + 1567613, + 1567643, + 1567672, + 1567702, + 1567731, + 1567761, + 1567790, + 1567820, + 1567850, + 1567879, + 1567909, + 1567938, + 1567968, + 1567997, + 1568027, + 1568056, + 1568086, + 1568115, + 1568144, + 1568174, + 1568204, + 1568233, + 1568263, + 1568293, + 1568322, + 1568352, + 1568381, + 1568411, + 1568440, + 1568469, + 1568499, + 1568528, + 1568558, + 1568587, + 1568617, + 1568647, + 1568677, + 1568706, + 1568736, + 1568765, + 1568795, + 1568824, + 1568853, + 1568883, + 1568912, + 1568941, + 1568971, + 1569001, + 1569031, + 1569060, + 1569090, + 1569120, + 1569149, + 1569179, + 1569208, + 1569237, + 1569267, + 1569296, + 1569325, + 1569355, + 1569385, + 1569415, + 1569444, + 1569474, + 1569504, + 1569533, + 1569563, + 1569592, + 1569621, + 1569651, + 1569680, + 1569709, + 1569739, + 1569769, + 1569799, + 1569828, + 1569858, + 1569887, + 1569917, + 1569947, + 1569976, + 1570005, + 1570035, + 1570064, + 1570094, + 1570123, + 1570153, + 1570182, + 1570212, + 1570241, + 1570271, + 1570301, + 1570330, + 1570360, + 1570389, + 1570419, + 1570448, + 1570478, + 1570508, + 1570537, + 1570566, + 1570596, + 1570625, + 1570655, + 1570684, + 1570714, + 1570744, + 1570773, + 1570803, + 1570833, + 1570862, + 1570892, + 1570921, + 1570950, + 1570979, + 1571009, + 1571038, + 1571068, + 1571098, + 1571127, + 1571157, + 1571187, + 1571217, + 1571246, + 1571276, + 1571305, + 1571334, + 1571363, + 1571393, + 1571422, + 1571452, + 1571481, + 1571511, + 1571541, + 1571571, + 1571601, + 1571630, + 1571659, + 1571689, + 1571718, + 1571747, + 1571777, + 1571806, + 1571836, + 1571865, + 1571895, + 1571925, + 1571955, + 1571984, + 1572014, + 1572043, + 1572073, + 1572102, + 1572131, + 1572161, + 1572190, + 1572220, + 1572249, + 1572279, + 1572309, + 1572338, + 1572368, + 1572398, + 1572428, + 1572457, + 1572486, + 1572515, + 1572545, + 1572574, + 1572604, + 1572633, + 1572663, + 1572692, + 1572722, + 1572752, + 1572781, + 1572811, + 1572841, + 1572870, + 1572900, + 1572929, + 1572958, + 1572988, + 1573017, + 1573047, + 1573076, + 1573106, + 1573135, + 1573165, + 1573195, + 1573224, + 1573254, + 1573284, + 1573313, + 1573342, + 1573372, + 1573401, + 1573430, + 1573460, + 1573489, + 1573519, + 1573549, + 1573578, + 1573608, + 1573638, + 1573667, + 1573697, + 1573726, + 1573756, + 1573785, + 1573814, + 1573844, + 1573873, + 1573903, + 1573933, + 1573962, + 1573992, + 1574022, + 1574051, + 1574081, + 1574110, + 1574140, + 1574169, + 1574198, + 1574228, + 1574257, + 1574287, + 1574316, + 1574346, + 1574376, + 1574405, + 1574435, + 1574465, + 1574494, + 1574524, + 1574553, + 1574583, + 1574612, + 1574641, + 1574671, + 1574700, + 1574730, + 1574759, + 1574789, + 1574819, + 1574848, + 1574878, + 1574908, + 1574937, + 1574967, + 1574996, + 1575025, + 1575055, + 1575084, + 1575114, + 1575143, + 1575173, + 1575202, + 1575232, + 1575262, + 1575292, + 1575321, + 1575351, + 1575380, + 1575409, + 1575439, + 1575468, + 1575497, + 1575527, + 1575556, + 1575586, + 1575616, + 1575646, + 1575676, + 1575705, + 1575735, + 1575764, + 1575793, + 1575823, + 1575852, + 1575881, + 1575911, + 1575940, + 1575970, + 1576000, + 1576030, + 1576059, + 1576089, + 1576119, + 1576148, + 1576177, + 1576207, + 1576236, + 1576265, + 1576295, + 1576324, + 1576354, + 1576384, + 1576413, + 1576443, + 1576473, + 1576502, + 1576532, + 1576561, + 1576591, + 1576620, + 1576649, + 1576679, + 1576709, + 1576738, + 1576768, + 1576797, + 1576827, + 1576856, + 1576886, + 1576916, + 1576945, + 1576975, + 1577004, + 1577034, + 1577063, + 1577093, + 1577122, + 1577152, + 1577181, + 1577210, + 1577240, + 1577270, + 1577299, + 1577329, + 1577359, + 1577388, + 1577418, + 1577447, + 1577477, + 1577506, + 1577535, + 1577565, + 1577594, + 1577624, + 1577653, + 1577683, + 1577713, + 1577743, + 1577772, + 1577802, + 1577832, + 1577861, + 1577890, + 1577919, + 1577949, + 1577978, + 1578007, + 1578037, + 1578067, + 1578097, + 1578127, + 1578156, + 1578186, + 1578215, + 1578245, + 1578274, + 1578303, + 1578333, + 1578362, + 1578391, + 1578421, + 1578451, + 1578480, + 1578510, + 1578540, + 1578570, + 1578599, + 1578629, + 1578658, + 1578687, + 1578717, + 1578746, + 1578775, + 1578805, + 1578835, + 1578864, + 1578894, + 1578924, + 1578953, + 1578983, + 1579012, + 1579042, + 1579071, + 1579101, + 1579130, + 1579160, + 1579189, + 1579219, + 1579248, + 1579278, + 1579307, + 1579337, + 1579367, + 1579396, + 1579426, + 1579455, + 1579485, + 1579514, + 1579544, + 1579573, + 1579603, + 1579632, + 1579661, + 1579691, + 1579721, + 1579750, + 1579780, + 1579810, + 1579839, + 1579869, + 1579898, + 1579928, + 1579957, + 1579986, + 1580016, + 1580045, + 1580075, + 1580104, + 1580134, + 1580164, + 1580193, + 1580223, + 1580253, + 1580282, + 1580312, + 1580341, + 1580370, + 1580400, + 1580429, + 1580459, + 1580488, + 1580518, + 1580547, + 1580577, + 1580607, + 1580637, + 1580666, + 1580696, + 1580725, + 1580754, + 1580784, + 1580813, + 1580843, + 1580872, + 1580902, + 1580931, + 1580961, + 1580991, + 1581020, + 1581050, + 1581079, + 1581109, + 1581139, + 1581168, + 1581197, + 1581227, + 1581256, + 1581286, + 1581315, + 1581345, + 1581374, + 1581404, + 1581434, + 1581463, + 1581493, + 1581522, + 1581552, + 1581582, + 1581611, + 1581640, + 1581669, + 1581699, + 1581728, + 1581758, + 1581788, + 1581817, + 1581847, + 1581877, + 1581907, + 1581936, + 1581966, + 1581995, + 1582024, + 1582053, + 1582083, + 1582112, + 1582142, + 1582171, + 1582201, + 1582231, + 1582261, + 1582290, + 1582320, + 1582349, + 1582379, + 1582408, + 1582437, + 1582467, + 1582496, + 1582526, + 1582555, + 1582585, + 1582615, + 1582645, + 1582674, + 1582704, + 1582733, + 1582763, + 1582792, + 1582821, + 1582851, + 1582880, + 1582910, + 1582939, + 1582969, + 1582999, + 1583028, + 1583058, + 1583088, + 1583117, + 1583147, + 1583176, + 1583205, + 1583235, + 1583265, + 1583294, + 1583324, + 1583353, + 1583382, + 1583412, + 1583442, + 1583471, + 1583501, + 1583530, + 1583560, + 1583589, + 1583619, + 1583649, + 1583678, + 1583708, + 1583737, + 1583766, + 1583796, + 1583825, + 1583855, + 1583884, + 1583914, + 1583944, + 1583974, + 1584003, + 1584033, + 1584062, + 1584091, + 1584121, + 1584150, + 1584180, + 1584209, + 1584238, + 1584268, + 1584298, + 1584328, + 1584358, + 1584387, + 1584417, + 1584446, + 1584475, + 1584505, + 1584534, + 1584563, + 1584593, + 1584622, + 1584652, + 1584682, + 1584712, + 1584742, + 1584771, + 1584801, + 1584830, + 1584859, + 1584889, + 1584918, + 1584947, + 1584977, + 1585006, + 1585036, + 1585066, + 1585096, + 1585125, + 1585155, + 1585184, + 1585214, + 1585243, + 1585273, + 1585302, + 1585331, + 1585361, + 1585390, + 1585420, + 1585450, + 1585479, + 1585509, + 1585539, + 1585568, + 1585598, + 1585627, + 1585657, + 1585686, + 1585715, + 1585745, + 1585774, + 1585804, + 1585834, + 1585863, + 1585893, + 1585922, + 1585952, + 1585982, + 1586011, + 1586041, + 1586070, + 1586100, + 1586129, + 1586159, + 1586188, + 1586217, + 1586247, + 1586276, + 1586306, + 1586336, + 1586365, + 1586395, + 1586425, + 1586454, + 1586484, + 1586513, + 1586543, + 1586572, + 1586601, + 1586631, + 1586660, + 1586690, + 1586719, + 1586749, + 1586779, + 1586808, + 1586838, + 1586867, + 1586897, + 1586926, + 1586956, + 1586985, + 1587015, + 1587044, + 1587074, + 1587103, + 1587133, + 1587162, + 1587192, + 1587222, + 1587252, + 1587281, + 1587310, + 1587340, + 1587369, + 1587399, + 1587428, + 1587457, + 1587487, + 1587517, + 1587546, + 1587576, + 1587606, + 1587635, + 1587665, + 1587694, + 1587724, + 1587753, + 1587783, + 1587812, + 1587841, + 1587871, + 1587900, + 1587930, + 1587960, + 1587989, + 1588019, + 1588049, + 1588078, + 1588108, + 1588137, + 1588167, + 1588196, + 1588225, + 1588255, + 1588284, + 1588314, + 1588343, + 1588373, + 1588403, + 1588432, + 1588462, + 1588492, + 1588521, + 1588551, + 1588580, + 1588609, + 1588639, + 1588668, + 1588697, + 1588727, + 1588757, + 1588786, + 1588816, + 1588846, + 1588876, + 1588905, + 1588935, + 1588964, + 1588993, + 1589023, + 1589052, + 1589081, + 1589111, + 1589141, + 1589170, + 1589200, + 1589230, + 1589260, + 1589289, + 1589319, + 1589348, + 1589377, + 1589407, + 1589436, + 1589466, + 1589495, + 1589525, + 1589554, + 1589584, + 1589614, + 1589643, + 1589673, + 1589702, + 1589732, + 1589761, + 1589791, + 1589820, + 1589850, + 1589879, + 1589909, + 1589938, + 1589968, + 1589997, + 1590027, + 1590056, + 1590086, + 1590116, + 1590145, + 1590175, + 1590204, + 1590234, + 1590263, + 1590293, + 1590322, + 1590352, + 1590381, + 1590411, + 1590440, + 1590470, + 1590499, + 1590529, + 1590559, + 1590589, + 1590618, + 1590648, + 1590677, + 1590706, + 1590735, + 1590765, + 1590794, + 1590824, + 1590853, + 1590883, + 1590913, + 1590943, + 1590973, + 1591002, + 1591031, + 1591061, + 1591090, + 1591119, + 1591149, + 1591178, + 1591208, + 1591237, + 1591267, + 1591297, + 1591327, + 1591357, + 1591386, + 1591415, + 1591445, + 1591474, + 1591503, + 1591533, + 1591562, + 1591592, + 1591621, + 1591651, + 1591681, + 1591711, + 1591740, + 1591770, + 1591799, + 1591829, + 1591858, + 1591887, + 1591917, + 1591946, + 1591976, + 1592005, + 1592035, + 1592065, + 1592094, + 1592124, + 1592153, + 1592183, + 1592213, + 1592242, + 1592271, + 1592301, + 1592330, + 1592360, + 1592389, + 1592419, + 1592448, + 1592478, + 1592507, + 1592537, + 1592567, + 1592596, + 1592626, + 1592656, + 1592685, + 1592714, + 1592744, + 1592773, + 1592803, + 1592832, + 1592862, + 1592891, + 1592921, + 1592951, + 1592980, + 1593010, + 1593040, + 1593069, + 1593099, + 1593128, + 1593157, + 1593186, + 1593216, + 1593245, + 1593275, + 1593305, + 1593334, + 1593364, + 1593394, + 1593424, + 1593453, + 1593483, + 1593512, + 1593541, + 1593570, + 1593600, + 1593629, + 1593659, + 1593688, + 1593718, + 1593748, + 1593778, + 1593807, + 1593837, + 1593866, + 1593896, + 1593925, + 1593955, + 1593984, + 1594013, + 1594043, + 1594072, + 1594102, + 1594132, + 1594161, + 1594191, + 1594221, + 1594250, + 1594280, + 1594309, + 1594339, + 1594368, + 1594397, + 1594427, + 1594456, + 1594486, + 1594515, + 1594545, + 1594575, + 1594604, + 1594634, + 1594664, + 1594693, + 1594723, + 1594752, + 1594781, + 1594811, + 1594840, + 1594870, + 1594899, + 1594929, + 1594958, + 1594988, + 1595018, + 1595048, + 1595077, + 1595107, + 1595136, + 1595165, + 1595195, + 1595224, + 1595253, + 1595283, + 1595312, + 1595342, + 1595372, + 1595402, + 1595431, + 1595461, + 1595491, + 1595520, + 1595549, + 1595579, + 1595608, + 1595637, + 1595667, + 1595696, + 1595726, + 1595756, + 1595785, + 1595815, + 1595845, + 1595874, + 1595904, + 1595933, + 1595963, + 1595992, + 1596021, + 1596051, + 1596080, + 1596110, + 1596140, + 1596169, + 1596199, + 1596228, + 1596258, + 1596288, + 1596317, + 1596347, + 1596376, + 1596406, + 1596435, + 1596465, + 1596494, + 1596524, + 1596553, + 1596583, + 1596612, + 1596642, + 1596671, + 1596701, + 1596731, + 1596760, + 1596790, + 1596819, + 1596849, + 1596878, + 1596907, + 1596937, + 1596966, + 1596996, + 1597025, + 1597055, + 1597085, + 1597115, + 1597144, + 1597174, + 1597204, + 1597233, + 1597262, + 1597291, + 1597321, + 1597350, + 1597380, + 1597409, + 1597439, + 1597469, + 1597499, + 1597528, + 1597558, + 1597587, + 1597617, + 1597646, + 1597675, + 1597705, + 1597734, + 1597763, + 1597793, + 1597823, + 1597853, + 1597883, + 1597912, + 1597942, + 1597971, + 1598001, + 1598030, + 1598059, + 1598089, + 1598118, + 1598147, + 1598177, + 1598207, + 1598237, + 1598266, + 1598296, + 1598326, + 1598355, + 1598385, + 1598414, + 1598443, + 1598473, + 1598502, + 1598531, + 1598561, + 1598591, + 1598620, + 1598650, + 1598680, + 1598709, + 1598739, + 1598768, + 1598798, + 1598827, + 1598857, + 1598886, + 1598916, + 1598945, + 1598975, + 1599004, + 1599034, + 1599063, + 1599093, + 1599123, + 1599152, + 1599182, + 1599211, + 1599241, + 1599270, + 1599300, + 1599329, + 1599359, + 1599388, + 1599417, + 1599447, + 1599477, + 1599506, + 1599536, + 1599566, + 1599595, + 1599625, + 1599654, + 1599684, + 1599713, + 1599742, + 1599772, + 1599801, + 1599831, + 1599860, + 1599890, + 1599920, + 1599949, + 1599979, + 1600009, + 1600038, + 1600068, + 1600097, + 1600126, + 1600156, + 1600185, + 1600215, + 1600244, + 1600274, + 1600303, + 1600333, + 1600363, + 1600393, + 1600422, + 1600452, + 1600481, + 1600510, + 1600540, + 1600569, + 1600599, + 1600628, + 1600658, + 1600687, + 1600717, + 1600747, + 1600776, + 1600806, + 1600835, + 1600865, + 1600895, + 1600924, + 1600953, + 1600983, + 1601012, + 1601042, + 1601071, + 1601101, + 1601130, + 1601160, + 1601190, + 1601219, + 1601249, + 1601279, + 1601308, + 1601337, + 1601367, + 1601396, + 1601425, + 1601455, + 1601484, + 1601514, + 1601544, + 1601573, + 1601603, + 1601633, + 1601663, + 1601692, + 1601721, + 1601751, + 1601780, + 1601809, + 1601839, + 1601868, + 1601898, + 1601927, + 1601957, + 1601987, + 1602017, + 1602046, + 1602076, + 1602105, + 1602135, + 1602164, + 1602193, + 1602223, + 1602252, + 1602282, + 1602311, + 1602341, + 1602371, + 1602400, + 1602430, + 1602460, + 1602489, + 1602519, + 1602548, + 1602577, + 1602607, + 1602636, + 1602666, + 1602695, + 1602725, + 1602755, + 1602784, + 1602814, + 1602843, + 1602873, + 1602902, + 1602932, + 1602961, + 1602991, + 1603021, + 1603050, + 1603079, + 1603109, + 1603138, + 1603168, + 1603197, + 1603227, + 1603257, + 1603286, + 1603316, + 1603346, + 1603375, + 1603405, + 1603434, + 1603463, + 1603493, + 1603522, + 1603552, + 1603581, + 1603611, + 1603640, + 1603670, + 1603700, + 1603730, + 1603759, + 1603789, + 1603818, + 1603847, + 1603877, + 1603906, + 1603936, + 1603965, + 1603994, + 1604024, + 1604054, + 1604084, + 1604114, + 1604143, + 1604173, + 1604202, + 1604231, + 1604261, + 1604290, + 1604319, + 1604349, + 1604378, + 1604408, + 1604438, + 1604468, + 1604498, + 1604527, + 1604556, + 1604586, + 1604615, + 1604645, + 1604674, + 1604703, + 1604733, + 1604762, + 1604792, + 1604822, + 1604852, + 1604881, + 1604911, + 1604940, + 1604970, + 1604999, + 1605029, + 1605058, + 1605087, + 1605117, + 1605146, + 1605176, + 1605206, + 1605235, + 1605265, + 1605294, + 1605324, + 1605353, + 1605383, + 1605413, + 1605442, + 1605472, + 1605501, + 1605531, + 1605560, + 1605590, + 1605619, + 1605648, + 1605678, + 1605708, + 1605737, + 1605767, + 1605797, + 1605826, + 1605856, + 1605885, + 1605915, + 1605944, + 1605973, + 1606003, + 1606032, + 1606062, + 1606091, + 1606121, + 1606151, + 1606180, + 1606210, + 1606240, + 1606269, + 1606299, + 1606328, + 1606357, + 1606387, + 1606416, + 1606446, + 1606475, + 1606505, + 1606535, + 1606564, + 1606594, + 1606624, + 1606653, + 1606683, + 1606712, + 1606741, + 1606771, + 1606800, + 1606829, + 1606859, + 1606889, + 1606918, + 1606949, + 1606978, + 1607008, + 1607037, + 1607066, + 1607096, + 1607125, + 1607155, + 1607184, + 1607213, + 1607243, + 1607273, + 1607302, + 1607332, + 1607362, + 1607391, + 1607421, + 1607450, + 1607480, + 1607509, + 1607539, + 1607568, + 1607597, + 1607627, + 1607656, + 1607686, + 1607716, + 1607745, + 1607775, + 1607805, + 1607834, + 1607864, + 1607893, + 1607923, + 1607952, + 1607981, + 1608011, + 1608040, + 1608070, + 1608099, + 1608129, + 1608159, + 1608188, + 1608218, + 1608248, + 1608277, + 1608307, + 1608336, + 1608365, + 1608395, + 1608424, + 1608454, + 1608483, + 1608513, + 1608542, + 1608572, + 1608602, + 1608632, + 1608661, + 1608691, + 1608720, + 1608749, + 1608779, + 1608808, + 1608838, + 1608867, + 1608897, + 1608926, + 1608956, + 1608986, + 1609015, + 1609045, + 1609075, + 1609104, + 1609133, + 1609163, + 1609192, + 1609222, + 1609251, + 1609281, + 1609310, + 1609340, + 1609369, + 1609399, + 1609429, + 1609458, + 1609488, + 1609517, + 1609547, + 1609576, + 1609606, + 1609635, + 1609665, + 1609694, + 1609724, + 1609753, + 1609783, + 1609812, + 1609842, + 1609872, + 1609901, + 1609931, + 1609961, + 1609990, + 1610019, + 1610049, + 1610078, + 1610107, + 1610137, + 1610166, + 1610196, + 1610226, + 1610255, + 1610285, + 1610315, + 1610345, + 1610374, + 1610403, + 1610433, + 1610462, + 1610491, + 1610521, + 1610550, + 1610580, + 1610609, + 1610639, + 1610669, + 1610699, + 1610729, + 1610758, + 1610787, + 1610817, + 1610846, + 1610875, + 1610905, + 1610934, + 1610963, + 1610993, + 1611023, + 1611053, + 1611083, + 1611112, + 1611142, + 1611171, + 1611201, + 1611230, + 1611259, + 1611289, + 1611318, + 1611348, + 1611377, + 1611407, + 1611437, + 1611467, + 1611496, + 1611526, + 1611555, + 1611585, + 1611614, + 1611643, + 1611673, + 1611702, + 1611732, + 1611761, + 1611791, + 1611821, + 1611850, + 1611880, + 1611909, + 1611939, + 1611969, + 1611998, + 1612027, + 1612057, + 1612086, + 1612116, + 1612145, + 1612175, + 1612204, + 1612234, + 1612263, + 1612293, + 1612323, + 1612352, + 1612382, + 1612412, + 1612441, + 1612471, + 1612500, + 1612529, + 1612559, + 1612588, + 1612618, + 1612647, + 1612677, + 1612706, + 1612736, + 1612766, + 1612796, + 1612825, + 1612855, + 1612884, + 1612913, + 1612942, + 1612972, + 1613001, + 1613031, + 1613060, + 1613090, + 1613120, + 1613150, + 1613180, + 1613209, + 1613239, + 1613268, + 1613297, + 1613327, + 1613356, + 1613385, + 1613415, + 1613444, + 1613474, + 1613504, + 1613534, + 1613563, + 1613593, + 1613622, + 1613652, + 1613681, + 1613711, + 1613740, + 1613769, + 1613799, + 1613828, + 1613858, + 1613887, + 1613917, + 1613947, + 1613977, + 1614006, + 1614036, + 1614065, + 1614095, + 1614124, + 1614153, + 1614183, + 1614212, + 1614242, + 1614271, + 1614301, + 1614331, + 1614361, + 1614390, + 1614420, + 1614449, + 1614479, + 1614508, + 1614537, + 1614567, + 1614596, + 1614626, + 1614655, + 1614685, + 1614714, + 1614744, + 1614774, + 1614803, + 1614833, + 1614863, + 1614892, + 1614921, + 1614951, + 1614980, + 1615010, + 1615039, + 1615068, + 1615098, + 1615128, + 1615158, + 1615187, + 1615217, + 1615247, + 1615276, + 1615305, + 1615335, + 1615364, + 1615393, + 1615423, + 1615452, + 1615482, + 1615512, + 1615541, + 1615571, + 1615601, + 1615630, + 1615660, + 1615689, + 1615719, + 1615748, + 1615778, + 1615807, + 1615837, + 1615866, + 1615896, + 1615925, + 1615955, + 1615984, + 1616014, + 1616044, + 1616073, + 1616103, + 1616132, + 1616162, + 1616191, + 1616221, + 1616250, + 1616279, + 1616309, + 1616338, + 1616368, + 1616398, + 1616427, + 1616457, + 1616487, + 1616516, + 1616546, + 1616575, + 1616605, + 1616634, + 1616663, + 1616693, + 1616722, + 1616752, + 1616781, + 1616811, + 1616841, + 1616871, + 1616900, + 1616930, + 1616959, + 1616989, + 1617018, + 1617047, + 1617077, + 1617106, + 1617136, + 1617165, + 1617195, + 1617225, + 1617255, + 1617284, + 1617314, + 1617343, + 1617373, + 1617402, + 1617431, + 1617461, + 1617490, + 1617519, + 1617549, + 1617579, + 1617609, + 1617638, + 1617668, + 1617698, + 1617727, + 1617757, + 1617786, + 1617815, + 1617845, + 1617874, + 1617903, + 1617933, + 1617963, + 1617993, + 1618022, + 1618052, + 1618081, + 1618111, + 1618141, + 1618170, + 1618199, + 1618229, + 1618258, + 1618288, + 1618317, + 1618347, + 1618376, + 1618406, + 1618435, + 1618465, + 1618495, + 1618524, + 1618554, + 1618583, + 1618613, + 1618642, + 1618672, + 1618701, + 1618731, + 1618760, + 1618790, + 1618819, + 1618849, + 1618878, + 1618908, + 1618937, + 1618967, + 1618997, + 1619026, + 1619056, + 1619085, + 1619115, + 1619144, + 1619173, + 1619203, + 1619232, + 1619262, + 1619292, + 1619321, + 1619351, + 1619381, + 1619411, + 1619440, + 1619469, + 1619499, + 1619528, + 1619557, + 1619587, + 1619616, + 1619646, + 1619675, + 1619705, + 1619735, + 1619765, + 1619795, + 1619824, + 1619853, + 1619883, + 1619912, + 1619941, + 1619971, + 1620000, + 1620030, + 1620059, + 1620089, + 1620119, + 1620149, + 1620178, + 1620208, + 1620237, + 1620267, + 1620296, + 1620325, + 1620355, + 1620384, + 1620414, + 1620443, + 1620473, + 1620503, + 1620532, + 1620562, + 1620591, + 1620621, + 1620651, + 1620680, + 1620709, + 1620739, + 1620768, + 1620798, + 1620827, + 1620857, + 1620886, + 1620916, + 1620946, + 1620975, + 1621005, + 1621035, + 1621064, + 1621093, + 1621123, + 1621152, + 1621182, + 1621211, + 1621240, + 1621270, + 1621300, + 1621329, + 1621359, + 1621389, + 1621418, + 1621448, + 1621477, + 1621507, + 1621536, + 1621566, + 1621595, + 1621624, + 1621654, + 1621683, + 1621713, + 1621743, + 1621773, + 1621802, + 1621832, + 1621861, + 1621891, + 1621920, + 1621949, + 1621979, + 1622008, + 1622038, + 1622067, + 1622097, + 1622127, + 1622156, + 1622186, + 1622216, + 1622245, + 1622275, + 1622304, + 1622333, + 1622363, + 1622392, + 1622422, + 1622451, + 1622481, + 1622510, + 1622540, + 1622570, + 1622599, + 1622629, + 1622658, + 1622688, + 1622718, + 1622747, + 1622777, + 1622806, + 1622835, + 1622865, + 1622894, + 1622924, + 1622953, + 1622983, + 1623013, + 1623042, + 1623072, + 1623102, + 1623131, + 1623161, + 1623190, + 1623219, + 1623249, + 1623278, + 1623308, + 1623337, + 1623366, + 1623396, + 1623426, + 1623456, + 1623486, + 1623515, + 1623545, + 1623574, + 1623603, + 1623633, + 1623662, + 1623691, + 1623721, + 1623750, + 1623780, + 1623810, + 1623840, + 1623869, + 1623899, + 1623929, + 1623958, + 1623987, + 1624017, + 1624046, + 1624075, + 1624105, + 1624134, + 1624164, + 1624194, + 1624224, + 1624253, + 1624283, + 1624313, + 1624342, + 1624371, + 1624401, + 1624430, + 1624459, + 1624489, + 1624518, + 1624548, + 1624578, + 1624607, + 1624637, + 1624667, + 1624696, + 1624726, + 1624755, + 1624785, + 1624814, + 1624843, + 1624873, + 1624903, + 1624932, + 1624962, + 1624991, + 1625021, + 1625050, + 1625080, + 1625110, + 1625139, + 1625169, + 1625198, + 1625227, + 1625257, + 1625287, + 1625316, + 1625345, + 1625375, + 1625404, + 1625434, + 1625464, + 1625493, + 1625523, + 1625553, + 1625582, + 1625612, + 1625641, + 1625671, + 1625700, + 1625729, + 1625759, + 1625788, + 1625818, + 1625847, + 1625877, + 1625907, + 1625937, + 1625966, + 1625996, + 1626025, + 1626055, + 1626084, + 1626113, + 1626143, + 1626172, + 1626201, + 1626231, + 1626261, + 1626291, + 1626320, + 1626350, + 1626380, + 1626409, + 1626439, + 1626468, + 1626497, + 1626527, + 1626556, + 1626585, + 1626615, + 1626645, + 1626674, + 1626704, + 1626734, + 1626764, + 1626793, + 1626822, + 1626852, + 1626881, + 1626911, + 1626940, + 1626969, + 1626999, + 1627029, + 1627058, + 1627088, + 1627118, + 1627147, + 1627177, + 1627206, + 1627236, + 1627265, + 1627295, + 1627324, + 1627353, + 1627383, + 1627412, + 1627442, + 1627472, + 1627501, + 1627531, + 1627561, + 1627590, + 1627620, + 1627649, + 1627679, + 1627708, + 1627738, + 1627767, + 1627796, + 1627826, + 1627855, + 1627885, + 1627915, + 1627944, + 1627974, + 1628004, + 1628033, + 1628063, + 1628092, + 1628122, + 1628151, + 1628181, + 1628210, + 1628239, + 1628269, + 1628298, + 1628328, + 1628358, + 1628388, + 1628417, + 1628447, + 1628476, + 1628506, + 1628535, + 1628564, + 1628594, + 1628623, + 1628653, + 1628682, + 1628712, + 1628742, + 1628771, + 1628801, + 1628830, + 1628860, + 1628889, + 1628919, + 1628948, + 1628978, + 1629007, + 1629037, + 1629066, + 1629096, + 1629125, + 1629155, + 1629185, + 1629214, + 1629244, + 1629273, + 1629303, + 1629332, + 1629362, + 1629391, + 1629421, + 1629450, + 1629479, + 1629509, + 1629539, + 1629568, + 1629598, + 1629628, + 1629657, + 1629687, + 1629717, + 1629746, + 1629775, + 1629805, + 1629834, + 1629863, + 1629893, + 1629922, + 1629952, + 1629981, + 1630011, + 1630041, + 1630071, + 1630101, + 1630130, + 1630159, + 1630189, + 1630218, + 1630247, + 1630277, + 1630306, + 1630336, + 1630365, + 1630395, + 1630425, + 1630455, + 1630485, + 1630514, + 1630543, + 1630573, + 1630602, + 1630631, + 1630661, + 1630690, + 1630720, + 1630749, + 1630779, + 1630809, + 1630839, + 1630868, + 1630898, + 1630927, + 1630957, + 1630986, + 1631015, + 1631045, + 1631074, + 1631104, + 1631133, + 1631163, + 1631193, + 1631222, + 1631252, + 1631282, + 1631311, + 1631341, + 1631370, + 1631399, + 1631428, + 1631458, + 1631488, + 1631518, + 1631547, + 1631576, + 1631606, + 1631636, + 1631665, + 1631695, + 1631724, + 1631754, + 1631783, + 1631813, + 1631843, + 1631872, + 1631901, + 1631931, + 1631960, + 1631990, + 1632019, + 1632049, + 1632079, + 1632108, + 1632138, + 1632168, + 1632197, + 1632227, + 1632256, + 1632285, + 1632315, + 1632344, + 1632373, + 1632403, + 1632433, + 1632462, + 1632492, + 1632522, + 1632552, + 1632581, + 1632611, + 1632640, + 1632669, + 1632699, + 1632728, + 1632757, + 1632787, + 1632816, + 1632846, + 1632876, + 1632906, + 1632936, + 1632965, + 1632995, + 1633024, + 1633053, + 1633083, + 1633112, + 1633141, + 1633171, + 1633200, + 1633230, + 1633260, + 1633290, + 1633319, + 1633349, + 1633378, + 1633408, + 1633437, + 1633467, + 1633496, + 1633525, + 1633555, + 1633584, + 1633614, + 1633644, + 1633673, + 1633703, + 1633733, + 1633762, + 1633792, + 1633821, + 1633851, + 1633880, + 1633909, + 1633939, + 1633968, + 1633998, + 1634027, + 1634057, + 1634086, + 1634116, + 1634146, + 1634176, + 1634205, + 1634235, + 1634264, + 1634293, + 1634323, + 1634352, + 1634382, + 1634411, + 1634441, + 1634470, + 1634500, + 1634530, + 1634559, + 1634589, + 1634619, + 1634648, + 1634678, + 1634707, + 1634736, + 1634766, + 1634795, + 1634824, + 1634854, + 1634884, + 1634913, + 1634943, + 1634973, + 1635002, + 1635032, + 1635062, + 1635091, + 1635120, + 1635150, + 1635179, + 1635208, + 1635238, + 1635268, + 1635297, + 1635327, + 1635357, + 1635386, + 1635416, + 1635445, + 1635475, + 1635504, + 1635534, + 1635563, + 1635593, + 1635622, + 1635651, + 1635681, + 1635711, + 1635740, + 1635770, + 1635800, + 1635829, + 1635859, + 1635888, + 1635918, + 1635947, + 1635977, + 1636006, + 1636035, + 1636065, + 1636094, + 1636124, + 1636153, + 1636183, + 1636213, + 1636243, + 1636272, + 1636302, + 1636331, + 1636361, + 1636390, + 1636419, + 1636449, + 1636478, + 1636508, + 1636537, + 1636567, + 1636597, + 1636627, + 1636656, + 1636686, + 1636715, + 1636745, + 1636774, + 1636803, + 1636833, + 1636862, + 1636891, + 1636921, + 1636951, + 1636981, + 1637010, + 1637040, + 1637070, + 1637099, + 1637129, + 1637158, + 1637187, + 1637217, + 1637246, + 1637275, + 1637305, + 1637335, + 1637365, + 1637394, + 1637424, + 1637454, + 1637483, + 1637513, + 1637542, + 1637571, + 1637601, + 1637630, + 1637659, + 1637689, + 1637719, + 1637748, + 1637778, + 1637808, + 1637837, + 1637867, + 1637896, + 1637926, + 1637955, + 1637985, + 1638014, + 1638044, + 1638073, + 1638103, + 1638132, + 1638162, + 1638191, + 1638221, + 1638251, + 1638280, + 1638310, + 1638339, + 1638369, + 1638398, + 1638428, + 1638457, + 1638487, + 1638516, + 1638545, + 1638575, + 1638605, + 1638634, + 1638664, + 1638693, + 1638723, + 1638753, + 1638783, + 1638812, + 1638841, + 1638871, + 1638900, + 1638929, + 1638959, + 1638988, + 1639018, + 1639048, + 1639077, + 1639107, + 1639137, + 1639167, + 1639196, + 1639225, + 1639255, + 1639284, + 1639313, + 1639343, + 1639372, + 1639402, + 1639431, + 1639461, + 1639491, + 1639521, + 1639551, + 1639580, + 1639609, + 1639639, + 1639668, + 1639697, + 1639727, + 1639756, + 1639786, + 1639815, + 1639845, + 1639875, + 1639905, + 1639934, + 1639964, + 1639993, + 1640023, + 1640052, + 1640081, + 1640111, + 1640140, + 1640170, + 1640199, + 1640229, + 1640259, + 1640288, + 1640318, + 1640347, + 1640377, + 1640407, + 1640436, + 1640465, + 1640495, + 1640524, + 1640554, + 1640583, + 1640613, + 1640642, + 1640672, + 1640701, + 1640731, + 1640761, + 1640790, + 1640820, + 1640849, + 1640879, + 1640908, + 1640938, + 1640967, + 1640996, + 1641026, + 1641056, + 1641085, + 1641115, + 1641145, + 1641174, + 1641204, + 1641233, + 1641263, + 1641292, + 1641322, + 1641351, + 1641380, + 1641410, + 1641439, + 1641469, + 1641499, + 1641528, + 1641558, + 1641588, + 1641617, + 1641647, + 1641676, + 1641705, + 1641735, + 1641765, + 1641794, + 1641823, + 1641853, + 1641882, + 1641912, + 1641942, + 1641972, + 1642001, + 1642031, + 1642060, + 1642090, + 1642119, + 1642148, + 1642178, + 1642207, + 1642237, + 1642266, + 1642296, + 1642326, + 1642355, + 1642385, + 1642414, + 1642444, + 1642474, + 1642503, + 1642533, + 1642562, + 1642591, + 1642621, + 1642650, + 1642680, + 1642709, + 1642739, + 1642768, + 1642798, + 1642828, + 1642858, + 1642887, + 1642917, + 1642946, + 1642975, + 1643005, + 1643034, + 1643063, + 1643093, + 1643122, + 1643152, + 1643182, + 1643212, + 1643242, + 1643271, + 1643301, + 1643330, + 1643359, + 1643389, + 1643418, + 1643447, + 1643477, + 1643506, + 1643536, + 1643566, + 1643596, + 1643626, + 1643655, + 1643685, + 1643714, + 1643743, + 1643773, + 1643802, + 1643831, + 1643861, + 1643890, + 1643920, + 1643950, + 1643980, + 1644009, + 1644039, + 1644068, + 1644098, + 1644127, + 1644157, + 1644186, + 1644215, + 1644245, + 1644274, + 1644304, + 1644334, + 1644363, + 1644393, + 1644423, + 1644452, + 1644482, + 1644511, + 1644541, + 1644570, + 1644599, + 1644629, + 1644659, + 1644688, + 1644718, + 1644747, + 1644777, + 1644806, + 1644836, + 1644865, + 1644895, + 1644924, + 1644954, + 1644984, + 1645013, + 1645043, + 1645072, + 1645101, + 1645131, + 1645160, + 1645190, + 1645219, + 1645249, + 1645279, + 1645309, + 1645338, + 1645368, + 1645397, + 1645426, + 1645456, + 1645485, + 1645515, + 1645544, + 1645574, + 1645603, + 1645633, + 1645663, + 1645693, + 1645722, + 1645752, + 1645781, + 1645811, + 1645840, + 1645869, + 1645899, + 1645928, + 1645957, + 1645987, + 1646017, + 1646047, + 1646077, + 1646106, + 1646136, + 1646165, + 1646195, + 1646224, + 1646253, + 1646283, + 1646312, + 1646341, + 1646371, + 1646401, + 1646431, + 1646460, + 1646490, + 1646520, + 1646549, + 1646578, + 1646608, + 1646637, + 1646667, + 1646696, + 1646725, + 1646755, + 1646785, + 1646814, + 1646844, + 1646874, + 1646903, + 1646933, + 1646962, + 1646992, + 1647021, + 1647051, + 1647080, + 1647110, + 1647139, + 1647169, + 1647198, + 1647228, + 1647257, + 1647287, + 1647317, + 1647346, + 1647376, + 1647405, + 1647435, + 1647464, + 1647494, + 1647523, + 1647553, + 1647582, + 1647611, + 1647641, + 1647670, + 1647700, + 1647730, + 1647759, + 1647789, + 1647819, + 1647848, + 1647878, + 1647907, + 1647936, + 1647966, + 1647995, + 1648025, + 1648054, + 1648084, + 1648114, + 1648143, + 1648173, + 1648203, + 1648232, + 1648262, + 1648291, + 1648320, + 1648350, + 1648379, + 1648409, + 1648438, + 1648468, + 1648497, + 1648527, + 1648557, + 1648587, + 1648616, + 1648646, + 1648675, + 1648704, + 1648734, + 1648763, + 1648793, + 1648822, + 1648852, + 1648881, + 1648911, + 1648941, + 1648970, + 1649000, + 1649029, + 1649059, + 1649088, + 1649118, + 1649147, + 1649177, + 1649206, + 1649235, + 1649265, + 1649295, + 1649324, + 1649354, + 1649384, + 1649413, + 1649443, + 1649472, + 1649502, + 1649531, + 1649561, + 1649590, + 1649619, + 1649649, + 1649678, + 1649708, + 1649737, + 1649767, + 1649797, + 1649827, + 1649857, + 1649886, + 1649915, + 1649945, + 1649974, + 1650003, + 1650033, + 1650062, + 1650092, + 1650121, + 1650151, + 1650181, + 1650211, + 1650240, + 1650270, + 1650299, + 1650329, + 1650358, + 1650387, + 1650417, + 1650446, + 1650476, + 1650505, + 1650535, + 1650565, + 1650595, + 1650624, + 1650654, + 1650683, + 1650713, + 1650742, + 1650771, + 1650801, + 1650830, + 1650860, + 1650889, + 1650919, + 1650949, + 1650978, + 1651008, + 1651037, + 1651067, + 1651096, + 1651126, + 1651155, + 1651185, + 1651214, + 1651244, + 1651274, + 1651303, + 1651332, + 1651362, + 1651391, + 1651421, + 1651451, + 1651480, + 1651510, + 1651539, + 1651569, + 1651599, + 1651628, + 1651657, + 1651687, + 1651716, + 1651746, + 1651775, + 1651805, + 1651834, + 1651864, + 1651894, + 1651924, + 1651953, + 1651983, + 1652012, + 1652041, + 1652071, + 1652100, + 1652129, + 1652159, + 1652188, + 1652218, + 1652248, + 1652278, + 1652308, + 1652337, + 1652367, + 1652396, + 1652425, + 1652455, + 1652484, + 1652513, + 1652543, + 1652572, + 1652602, + 1652632, + 1652662, + 1652692, + 1652721, + 1652751, + 1652780, + 1652809, + 1652839, + 1652868, + 1652897, + 1652927, + 1652956, + 1652986, + 1653016, + 1653046, + 1653075, + 1653105, + 1653134, + 1653164, + 1653193, + 1653223, + 1653252, + 1653281, + 1653311, + 1653340, + 1653370, + 1653400, + 1653429, + 1653459, + 1653488, + 1653518, + 1653548, + 1653577, + 1653607, + 1653636, + 1653665, + 1653695, + 1653724, + 1653754, + 1653783, + 1653813, + 1653842, + 1653872, + 1653902, + 1653931, + 1653961, + 1653991, + 1654020, + 1654050, + 1654079, + 1654108, + 1654138, + 1654167, + 1654197, + 1654226, + 1654256, + 1654286, + 1654315, + 1654345, + 1654375, + 1654404, + 1654434, + 1654463, + 1654492, + 1654522, + 1654551, + 1654580, + 1654610, + 1654640, + 1654669, + 1654699, + 1654729, + 1654758, + 1654788, + 1654818, + 1654847, + 1654876, + 1654906, + 1654935, + 1654964, + 1654994, + 1655023, + 1655053, + 1655083, + 1655112, + 1655142, + 1655172, + 1655201, + 1655231, + 1655260, + 1655290, + 1655319, + 1655349, + 1655378, + 1655407, + 1655437, + 1655466, + 1655496, + 1655526, + 1655556, + 1655585, + 1655615, + 1655644, + 1655674, + 1655703, + 1655733, + 1655762, + 1655792, + 1655821, + 1655850, + 1655880, + 1655909, + 1655939, + 1655969, + 1655999, + 1656028, + 1656058, + 1656087, + 1656117, + 1656146, + 1656175, + 1656205, + 1656234, + 1656264, + 1656293, + 1656323, + 1656353, + 1656382, + 1656412, + 1656442, + 1656471, + 1656501, + 1656530, + 1656559, + 1656589, + 1656618, + 1656647, + 1656677, + 1656707, + 1656736, + 1656766, + 1656796, + 1656826, + 1656855, + 1656885, + 1656914, + 1656943, + 1656973, + 1657002, + 1657031, + 1657061, + 1657091, + 1657120, + 1657150, + 1657180, + 1657209, + 1657239, + 1657269, + 1657298, + 1657327, + 1657357, + 1657386, + 1657415, + 1657445, + 1657475, + 1657504, + 1657534, + 1657563, + 1657593, + 1657623, + 1657652, + 1657682, + 1657711, + 1657741, + 1657770, + 1657800, + 1657829, + 1657859, + 1657888, + 1657918, + 1657947, + 1657977, + 1658007, + 1658036, + 1658066, + 1658095, + 1658125, + 1658154, + 1658184, + 1658213, + 1658243, + 1658272, + 1658301, + 1658331, + 1658360, + 1658390, + 1658420, + 1658449, + 1658479, + 1658509, + 1658539, + 1658568, + 1658597, + 1658627, + 1658656, + 1658685, + 1658715, + 1658744, + 1658774, + 1658803, + 1658833, + 1658863, + 1658893, + 1658923, + 1658952, + 1658981, + 1659011, + 1659040, + 1659069, + 1659099, + 1659128, + 1659158, + 1659187, + 1659217, + 1659247, + 1659277, + 1659306, + 1659336, + 1659365, + 1659395, + 1659424, + 1659453, + 1659483, + 1659512, + 1659542, + 1659571, + 1659601, + 1659631, + 1659661, + 1659690, + 1659720, + 1659749, + 1659779, + 1659808, + 1659837, + 1659867, + 1659896, + 1659926, + 1659956, + 1659985, + 1660015, + 1660044, + 1660074, + 1660103, + 1660133, + 1660162, + 1660192, + 1660221, + 1660251, + 1660280, + 1660310, + 1660339, + 1660369, + 1660398, + 1660428, + 1660458, + 1660487, + 1660517, + 1660546, + 1660576, + 1660605, + 1660635, + 1660664, + 1660694, + 1660723, + 1660752, + 1660782, + 1660811, + 1660841, + 1660871, + 1660901, + 1660930, + 1660960, + 1660989, + 1661019, + 1661048, + 1661078, + 1661107, + 1661136, + 1661166, + 1661195, + 1661225, + 1661255, + 1661284, + 1661314, + 1661344, + 1661373, + 1661403, + 1661432, + 1661461, + 1661491, + 1661520, + 1661550, + 1661579, + 1661609, + 1661638, + 1661668, + 1661698, + 1661728, + 1661757, + 1661787, + 1661816, + 1661846, + 1661875, + 1661904, + 1661934, + 1661963, + 1661993, + 1662022, + 1662052, + 1662081, + 1662111, + 1662141, + 1662170, + 1662200, + 1662230, + 1662259, + 1662289, + 1662318, + 1662347, + 1662377, + 1662406, + 1662436, + 1662465, + 1662495, + 1662524, + 1662554, + 1662584, + 1662614, + 1662643, + 1662673, + 1662702, + 1662731, + 1662761, + 1662790, + 1662819, + 1662849, + 1662879, + 1662908, + 1662938, + 1662968, + 1662998, + 1663027, + 1663057, + 1663086, + 1663115, + 1663145, + 1663174, + 1663203, + 1663233, + 1663262, + 1663292, + 1663322, + 1663352, + 1663381, + 1663411, + 1663441, + 1663470, + 1663499, + 1663529, + 1663558, + 1663587, + 1663617, + 1663646, + 1663676, + 1663706, + 1663735, + 1663765, + 1663795, + 1663824, + 1663854, + 1663883, + 1663913, + 1663942, + 1663971, + 1664001, + 1664030, + 1664060, + 1664090, + 1664119, + 1664149, + 1664178, + 1664208, + 1664238, + 1664267, + 1664296, + 1664326, + 1664356, + 1664385, + 1664415, + 1664444, + 1664473, + 1664503, + 1664532, + 1664562, + 1664592, + 1664621, + 1664651, + 1664680, + 1664710, + 1664740, + 1664769, + 1664799, + 1664828, + 1664857, + 1664887, + 1664916, + 1664946, + 1664975, + 1665005, + 1665035, + 1665065, + 1665094, + 1665124, + 1665153, + 1665183, + 1665212, + 1665241, + 1665271, + 1665300, + 1665329, + 1665359, + 1665389, + 1665419, + 1665449, + 1665478, + 1665508, + 1665537, + 1665567, + 1665596, + 1665625, + 1665655, + 1665684, + 1665713, + 1665743, + 1665773, + 1665803, + 1665832, + 1665862, + 1665892, + 1665921, + 1665951, + 1665980, + 1666009, + 1666039, + 1666068, + 1666097, + 1666127, + 1666157, + 1666187, + 1666216, + 1666246, + 1666275, + 1666305, + 1666334, + 1666364, + 1666393, + 1666423, + 1666452, + 1666482, + 1666511, + 1666541, + 1666570, + 1666600, + 1666629, + 1666659, + 1666689, + 1666718, + 1666748, + 1666777, + 1666807, + 1666836, + 1666866, + 1666895, + 1666925, + 1666954, + 1666983, + 1667013, + 1667043, + 1667072, + 1667102, + 1667132, + 1667161, + 1667191, + 1667220, + 1667250, + 1667279, + 1667309, + 1667338, + 1667367, + 1667397, + 1667426, + 1667456, + 1667485, + 1667515, + 1667545, + 1667575, + 1667604, + 1667634, + 1667663, + 1667692, + 1667722, + 1667751, + 1667781, + 1667810, + 1667840, + 1667870, + 1667899, + 1667929, + 1667959, + 1667988, + 1668018, + 1668047, + 1668076, + 1668106, + 1668135, + 1668165, + 1668194, + 1668224, + 1668253, + 1668283, + 1668313, + 1668343, + 1668372, + 1668402, + 1668431, + 1668460, + 1668490, + 1668519, + 1668549, + 1668578, + 1668607, + 1668637, + 1668667, + 1668697, + 1668726, + 1668756, + 1668785, + 1668815, + 1668844, + 1668874, + 1668903, + 1668933, + 1668962, + 1668991, + 1669021, + 1669051, + 1669080, + 1669110, + 1669139, + 1669169, + 1669199, + 1669229, + 1669258, + 1669287, + 1669317, + 1669346, + 1669375, + 1669405, + 1669434, + 1669464, + 1669493, + 1669523, + 1669553, + 1669583, + 1669612, + 1669642, + 1669671, + 1669701, + 1669730, + 1669759, + 1669789, + 1669818, + 1669848, + 1669877, + 1669907, + 1669937, + 1669967, + 1669996, + 1670026, + 1670055, + 1670085, + 1670114, + 1670143, + 1670173, + 1670202, + 1670232, + 1670261, + 1670291, + 1670321, + 1670350, + 1670380, + 1670410, + 1670439, + 1670469, + 1670498, + 1670527, + 1670557, + 1670586, + 1670616, + 1670645, + 1670675, + 1670704, + 1670734, + 1670764, + 1670793, + 1670823, + 1670852, + 1670882, + 1670911, + 1670941, + 1670970, + 1671000, + 1671029, + 1671059, + 1671088, + 1671118, + 1671147, + 1671177, + 1671207, + 1671236, + 1671266, + 1671296, + 1671325, + 1671355, + 1671384, + 1671413, + 1671443, + 1671472, + 1671501, + 1671531, + 1671561, + 1671590, + 1671620, + 1671650, + 1671680, + 1671709, + 1671738, + 1671768, + 1671797, + 1671827, + 1671856, + 1671885, + 1671915, + 1671944, + 1671974, + 1672004, + 1672034, + 1672064, + 1672093, + 1672123, + 1672152, + 1672181, + 1672211, + 1672240, + 1672269, + 1672299, + 1672328, + 1672358, + 1672388, + 1672418, + 1672448, + 1672477, + 1672506, + 1672536, + 1672565, + 1672594, + 1672624, + 1672653, + 1672683, + 1672712, + 1672742, + 1672772, + 1672802, + 1672831, + 1672861, + 1672890, + 1672920, + 1672949, + 1672979, + 1673008, + 1673037, + 1673067, + 1673096, + 1673126, + 1673156, + 1673185, + 1673215, + 1673244, + 1673274, + 1673304, + 1673333, + 1673363, + 1673392, + 1673422, + 1673451, + 1673481, + 1673510, + 1673539, + 1673569, + 1673598, + 1673628, + 1673658, + 1673687, + 1673717, + 1673747, + 1673776, + 1673806, + 1673835, + 1673865, + 1673894, + 1673923, + 1673953, + 1673982, + 1674012, + 1674041, + 1674071, + 1674101, + 1674131, + 1674160, + 1674190, + 1674219, + 1674249, + 1674278, + 1674307, + 1674336, + 1674366, + 1674396, + 1674425, + 1674455, + 1674485, + 1674514, + 1674544, + 1674574, + 1674603, + 1674632, + 1674662, + 1674691, + 1674720, + 1674750, + 1674779, + 1674809, + 1674839, + 1674868, + 1674898, + 1674928, + 1674957, + 1674987, + 1675016, + 1675046, + 1675075, + 1675105, + 1675134, + 1675163, + 1675193, + 1675222, + 1675252, + 1675282, + 1675312, + 1675341, + 1675371, + 1675400, + 1675430, + 1675459, + 1675489, + 1675518, + 1675547, + 1675577, + 1675606, + 1675636, + 1675665, + 1675695, + 1675725, + 1675755, + 1675784, + 1675814, + 1675843, + 1675873, + 1675902, + 1675931, + 1675961, + 1675990, + 1676020, + 1676049, + 1676079, + 1676109, + 1676138, + 1676168, + 1676198, + 1676227, + 1676257, + 1676286, + 1676315, + 1676345, + 1676374, + 1676403, + 1676433, + 1676463, + 1676492, + 1676522, + 1676552, + 1676582, + 1676611, + 1676641, + 1676670, + 1676699, + 1676729, + 1676758, + 1676787, + 1676817, + 1676847, + 1676876, + 1676906, + 1676936, + 1676965, + 1676995, + 1677024, + 1677054, + 1677083, + 1677113, + 1677142, + 1677172, + 1677201, + 1677231, + 1677260, + 1677290, + 1677319, + 1677349, + 1677379, + 1677408, + 1677438, + 1677467, + 1677497, + 1677526, + 1677556, + 1677585, + 1677615, + 1677644, + 1677673, + 1677703, + 1677733, + 1677762, + 1677792, + 1677821, + 1677851, + 1677881, + 1677910, + 1677940, + 1677969, + 1677999, + 1678028, + 1678057, + 1678087, + 1678116, + 1678146, + 1678175, + 1678205, + 1678235, + 1678265, + 1678295, + 1678324, + 1678353, + 1678383, + 1678412, + 1678441, + 1678471, + 1678500, + 1678530, + 1678559, + 1678589, + 1678619, + 1678649, + 1678679, + 1678708, + 1678737, + 1678767, + 1678796, + 1678825, + 1678854, + 1678884, + 1678913, + 1678943, + 1678973, + 1679003, + 1679033, + 1679062, + 1679092, + 1679121, + 1679151, + 1679180, + 1679209, + 1679238, + 1679268, + 1679298, + 1679327, + 1679357, + 1679387, + 1679416, + 1679446, + 1679476, + 1679505, + 1679535, + 1679564, + 1679593, + 1679623, + 1679652, + 1679682, + 1679711, + 1679741, + 1679770, + 1679800, + 1679830, + 1679859, + 1679889, + 1679918, + 1679948, + 1679977, + 1680007, + 1680036, + 1680066, + 1680095, + 1680125, + 1680154, + 1680184, + 1680213, + 1680243, + 1680272, + 1680302, + 1680332, + 1680361, + 1680391, + 1680421, + 1680450, + 1680479, + 1680508, + 1680538, + 1680567, + 1680597, + 1680627, + 1680656, + 1680686, + 1680716, + 1680746, + 1680775, + 1680805, + 1680834, + 1680863, + 1680892, + 1680922, + 1680951, + 1680981, + 1681010, + 1681040, + 1681070, + 1681100, + 1681130, + 1681159, + 1681189, + 1681218, + 1681247, + 1681277, + 1681306, + 1681335, + 1681365, + 1681394, + 1681424, + 1681454, + 1681484, + 1681513, + 1681543, + 1681572, + 1681602, + 1681631, + 1681660, + 1681690, + 1681719, + 1681749, + 1681778, + 1681808, + 1681838, + 1681867, + 1681897, + 1681926, + 1681956, + 1681986, + 1682015, + 1682045, + 1682074, + 1682103, + 1682133, + 1682162, + 1682192, + 1682221, + 1682251, + 1682280, + 1682310, + 1682340, + 1682370, + 1682399, + 1682429, + 1682458, + 1682487, + 1682517, + 1682546, + 1682576, + 1682605, + 1682634, + 1682664, + 1682694, + 1682724, + 1682753, + 1682783, + 1682813, + 1682842, + 1682871, + 1682901, + 1682930, + 1682959, + 1682989, + 1683018, + 1683048, + 1683078, + 1683107, + 1683137, + 1683167, + 1683196, + 1683226, + 1683255, + 1683285, + 1683314, + 1683343, + 1683373, + 1683402, + 1683432, + 1683461, + 1683491, + 1683521, + 1683551, + 1683580, + 1683610, + 1683639, + 1683669, + 1683698, + 1683727, + 1683757, + 1683786, + 1683816, + 1683845, + 1683875, + 1683905, + 1683934, + 1683964, + 1683993, + 1684023, + 1684053, + 1684082, + 1684112, + 1684141, + 1684171, + 1684200, + 1684229, + 1684259, + 1684288, + 1684318, + 1684347, + 1684377, + 1684407, + 1684437, + 1684466, + 1684496, + 1684525, + 1684555, + 1684584, + 1684613, + 1684643, + 1684672, + 1684702, + 1684731, + 1684761, + 1684791, + 1684821, + 1684850, + 1684880, + 1684909, + 1684939, + 1684968, + 1684997, + 1685027, + 1685056, + 1685085, + 1685115, + 1685145, + 1685175, + 1685205, + 1685234, + 1685264, + 1685293, + 1685323, + 1685352, + 1685381, + 1685410, + 1685440, + 1685469, + 1685499, + 1685529, + 1685559, + 1685588, + 1685618, + 1685648, + 1685677, + 1685707, + 1685736, + 1685765, + 1685794, + 1685824, + 1685854, + 1685883, + 1685913, + 1685942, + 1685972, + 1686002, + 1686031, + 1686061, + 1686090, + 1686120, + 1686149, + 1686178, + 1686208, + 1686237, + 1686267, + 1686297, + 1686326, + 1686356, + 1686385, + 1686415, + 1686445, + 1686474, + 1686504, + 1686533, + 1686563, + 1686592, + 1686622, + 1686651, + 1686681, + 1686710, + 1686739, + 1686769, + 1686799, + 1686828, + 1686858, + 1686888, + 1686917, + 1686947, + 1686976, + 1687006, + 1687035, + 1687064, + 1687094, + 1687123, + 1687153, + 1687182, + 1687212, + 1687242, + 1687271, + 1687301, + 1687331, + 1687361, + 1687390, + 1687419, + 1687448, + 1687478, + 1687507, + 1687537, + 1687566, + 1687596, + 1687625, + 1687655, + 1687685, + 1687715, + 1687744, + 1687774, + 1687803, + 1687832, + 1687862, + 1687891, + 1687921, + 1687950, + 1687980, + 1688009, + 1688039, + 1688069, + 1688099, + 1688128, + 1688158, + 1688187, + 1688216, + 1688246, + 1688275, + 1688305, + 1688334, + 1688364, + 1688393, + 1688423, + 1688453, + 1688482, + 1688512, + 1688541, + 1688571, + 1688600, + 1688630, + 1688659, + 1688689, + 1688718, + 1688747, + 1688777, + 1688807, + 1688836, + 1688866, + 1688895, + 1688925, + 1688955, + 1688984, + 1689014, + 1689043, + 1689073, + 1689102, + 1689131, + 1689161, + 1689190, + 1689220, + 1689249, + 1689279, + 1689309, + 1689339, + 1689368, + 1689398, + 1689427, + 1689457, + 1689486, + 1689515, + 1689545, + 1689574, + 1689604, + 1689633, + 1689663, + 1689693, + 1689722, + 1689752, + 1689782, + 1689811, + 1689841, + 1689870, + 1689899, + 1689929, + 1689958, + 1689988, + 1690017, + 1690047, + 1690077, + 1690106, + 1690136, + 1690166, + 1690195, + 1690225, + 1690254, + 1690283, + 1690313, + 1690342, + 1690372, + 1690401, + 1690431, + 1690460, + 1690490, + 1690520, + 1690549, + 1690579, + 1690608, + 1690638, + 1690667, + 1690697, + 1690726, + 1690756, + 1690785, + 1690815, + 1690844, + 1690874, + 1690903, + 1690933, + 1690963, + 1690992, + 1691022, + 1691052, + 1691081, + 1691111, + 1691140, + 1691169, + 1691199, + 1691228, + 1691257, + 1691287, + 1691316, + 1691346, + 1691376, + 1691406, + 1691436, + 1691465, + 1691495, + 1691524, + 1691553, + 1691583, + 1691612, + 1691641, + 1691671, + 1691700, + 1691730, + 1691760, + 1691790, + 1691820, + 1691849, + 1691879, + 1691908, + 1691937, + 1691967, + 1691996, + 1692025, + 1692055, + 1692084, + 1692114, + 1692144, + 1692174, + 1692203, + 1692233, + 1692262, + 1692292, + 1692321, + 1692350, + 1692380, + 1692409, + 1692439, + 1692468, + 1692498, + 1692528, + 1692557, + 1692587, + 1692617, + 1692646, + 1692676, + 1692705, + 1692734, + 1692764, + 1692793, + 1692823, + 1692853, + 1692882, + 1692912, + 1692941, + 1692971, + 1693000, + 1693030, + 1693059, + 1693089, + 1693118, + 1693148, + 1693178, + 1693207, + 1693237, + 1693266, + 1693295, + 1693325, + 1693354, + 1693384, + 1693414, + 1693443, + 1693473, + 1693502, + 1693532, + 1693562, + 1693591, + 1693621, + 1693650, + 1693679, + 1693709, + 1693738, + 1693768, + 1693797, + 1693827, + 1693857, + 1693887, + 1693916, + 1693946, + 1693975, + 1694004, + 1694034, + 1694063, + 1694092, + 1694122, + 1694151, + 1694181, + 1694211, + 1694241, + 1694270, + 1694300, + 1694330, + 1694359, + 1694388, + 1694418, + 1694447, + 1694476, + 1694506, + 1694535, + 1694565, + 1694595, + 1694624, + 1694654, + 1694684, + 1694713, + 1694743, + 1694772, + 1694802, + 1694831, + 1694861, + 1694890, + 1694919, + 1694949, + 1694979, + 1695008, + 1695038, + 1695068, + 1695097, + 1695127, + 1695156, + 1695186, + 1695215, + 1695245, + 1695274, + 1695303, + 1695333, + 1695362, + 1695392, + 1695421, + 1695451, + 1695481, + 1695510, + 1695540, + 1695570, + 1695599, + 1695629, + 1695658, + 1695687, + 1695717, + 1695746, + 1695776, + 1695805, + 1695835, + 1695864, + 1695894, + 1695924, + 1695954, + 1695983, + 1696013, + 1696042, + 1696071, + 1696101, + 1696130, + 1696159, + 1696189, + 1696219, + 1696248, + 1696278, + 1696308, + 1696337, + 1696367, + 1696397, + 1696426, + 1696455, + 1696485, + 1696514, + 1696543, + 1696573, + 1696602, + 1696632, + 1696662, + 1696691, + 1696721, + 1696751, + 1696780, + 1696810, + 1696839, + 1696869, + 1696898, + 1696928, + 1696957, + 1696987, + 1697016, + 1697046, + 1697075, + 1697105, + 1697135, + 1697164, + 1697194, + 1697223, + 1697253, + 1697282, + 1697312, + 1697341, + 1697371, + 1697400, + 1697429, + 1697459, + 1697488, + 1697518, + 1697548, + 1697577, + 1697607, + 1697637, + 1697666, + 1697696, + 1697725, + 1697755, + 1697784, + 1697813, + 1697843, + 1697872, + 1697902, + 1697931, + 1697961, + 1697991, + 1698021, + 1698051, + 1698080, + 1698109, + 1698139, + 1698168, + 1698197, + 1698226, + 1698256, + 1698286, + 1698315, + 1698345, + 1698375, + 1698405, + 1698434, + 1698464, + 1698493, + 1698523, + 1698552, + 1698581, + 1698610, + 1698640, + 1698670, + 1698699, + 1698729, + 1698759, + 1698789, + 1698818, + 1698848, + 1698877, + 1698907, + 1698936, + 1698965, + 1698994, + 1699024, + 1699054, + 1699083, + 1699113, + 1699143, + 1699172, + 1699201, + 1699231, + 1699261, + 1699290, + 1699320, + 1699349, + 1699379, + 1699408, + 1699438, + 1699467, + 1699497, + 1699526, + 1699556, + 1699585, + 1699615, + 1699645, + 1699674, + 1699704, + 1699733, + 1699763, + 1699793, + 1699822, + 1699851, + 1699881, + 1699910, + 1699940, + 1699969, + 1699999, + 1700028, + 1700058, + 1700088, + 1700118, + 1700147, + 1700176, + 1700206, + 1700235, + 1700264, + 1700294, + 1700323, + 1700353, + 1700382, + 1700412, + 1700442, + 1700472, + 1700502, + 1700531, + 1700561, + 1700590, + 1700619, + 1700648, + 1700678, + 1700707, + 1700737, + 1700766, + 1700796, + 1700826, + 1700856, + 1700886, + 1700915, + 1700944, + 1700974, + 1701003, + 1701032, + 1701062, + 1701091, + 1701121, + 1701150, + 1701180, + 1701210, + 1701240, + 1701269, + 1701299, + 1701328, + 1701358, + 1701387, + 1701417, + 1701446, + 1701475, + 1701505, + 1701534, + 1701564, + 1701594, + 1701623, + 1701653, + 1701682, + 1701712, + 1701742, + 1701771, + 1701801, + 1701830, + 1701859, + 1701889, + 1701918, + 1701948, + 1701977, + 1702007, + 1702036, + 1702066, + 1702096, + 1702125, + 1702155, + 1702185, + 1702214, + 1702243, + 1702273, + 1702302, + 1702332, + 1702361, + 1702390, + 1702420, + 1702450, + 1702480, + 1702509, + 1702539, + 1702568, + 1702598, + 1702627, + 1702657, + 1702686, + 1702715, + 1702745, + 1702774, + 1702804, + 1702834, + 1702863, + 1702893, + 1702923, + 1702952, + 1702982, + 1703011, + 1703041, + 1703070, + 1703099, + 1703129, + 1703158, + 1703188, + 1703218, + 1703247, + 1703277, + 1703306, + 1703336, + 1703366, + 1703395, + 1703425, + 1703454, + 1703483, + 1703513, + 1703542, + 1703572, + 1703601, + 1703631, + 1703660, + 1703690, + 1703720, + 1703749, + 1703779, + 1703809, + 1703838, + 1703868, + 1703897, + 1703927, + 1703956, + 1703985, + 1704015, + 1704044, + 1704074, + 1704103, + 1704133, + 1704163, + 1704192, + 1704222, + 1704252, + 1704281, + 1704311, + 1704340, + 1704369, + 1704399, + 1704428, + 1704457, + 1704487, + 1704517, + 1704547, + 1704577, + 1704606, + 1704636, + 1704665, + 1704695, + 1704724, + 1704753, + 1704782, + 1704812, + 1704841, + 1704871, + 1704901, + 1704931, + 1704960, + 1704990, + 1705020, + 1705049, + 1705079, + 1705108, + 1705137, + 1705166, + 1705196, + 1705225, + 1705255, + 1705285, + 1705314, + 1705344, + 1705374, + 1705403, + 1705433, + 1705462, + 1705492, + 1705521, + 1705550, + 1705580, + 1705609, + 1705639, + 1705669, + 1705698, + 1705728, + 1705757, + 1705787, + 1705817, + 1705846, + 1705876, + 1705905, + 1705935, + 1705964, + 1705994, + 1706023, + 1706053, + 1706082, + 1706112, + 1706141, + 1706171, + 1706200, + 1706230, + 1706260, + 1706289, + 1706319, + 1706348, + 1706378, + 1706407, + 1706437, + 1706466, + 1706495, + 1706525, + 1706554, + 1706584, + 1706614, + 1706643, + 1706673, + 1706703, + 1706733, + 1706762, + 1706791, + 1706820, + 1706850, + 1706879, + 1706909, + 1706938, + 1706968, + 1706997, + 1707027, + 1707057, + 1707087, + 1707117, + 1707146, + 1707175, + 1707204, + 1707234, + 1707263, + 1707293, + 1707322, + 1707352, + 1707381, + 1707411, + 1707441, + 1707471, + 1707500, + 1707530, + 1707559, + 1707588, + 1707618, + 1707647, + 1707676, + 1707706, + 1707736, + 1707765, + 1707795, + 1707825, + 1707855, + 1707884, + 1707914, + 1707943, + 1707972, + 1708002, + 1708031, + 1708061, + 1708090, + 1708120, + 1708149, + 1708179, + 1708208, + 1708238, + 1708268, + 1708297, + 1708327, + 1708356, + 1708386, + 1708415, + 1708445, + 1708474, + 1708504, + 1708533, + 1708563, + 1708592, + 1708622, + 1708651, + 1708681, + 1708711, + 1708740, + 1708770, + 1708799, + 1708829, + 1708858, + 1708888, + 1708917, + 1708946, + 1708976, + 1709005, + 1709035, + 1709065, + 1709095, + 1709124, + 1709154, + 1709183, + 1709213, + 1709242, + 1709272, + 1709301, + 1709330, + 1709360, + 1709389, + 1709419, + 1709449, + 1709478, + 1709508, + 1709538, + 1709567, + 1709597, + 1709626, + 1709655, + 1709685, + 1709714, + 1709744, + 1709773, + 1709803, + 1709832, + 1709862, + 1709892, + 1709921, + 1709951, + 1709981, + 1710010, + 1710039, + 1710069, + 1710098, + 1710128, + 1710157, + 1710187, + 1710216, + 1710246, + 1710275, + 1710305, + 1710335, + 1710364, + 1710393, + 1710423, + 1710453, + 1710482, + 1710512, + 1710541, + 1710571, + 1710600, + 1710630, + 1710659, + 1710689, + 1710718, + 1710748, + 1710778, + 1710808, + 1710837, + 1710867, + 1710896, + 1710925, + 1710955, + 1710984, + 1711013, + 1711043, + 1711072, + 1711102, + 1711132, + 1711162, + 1711192, + 1711221, + 1711251, + 1711280, + 1711309, + 1711339, + 1711368, + 1711397, + 1711427, + 1711456, + 1711486, + 1711516, + 1711546, + 1711575, + 1711605, + 1711634, + 1711664, + 1711693, + 1711722, + 1711752, + 1711781, + 1711811, + 1711840, + 1711870, + 1711900, + 1711929, + 1711959, + 1711989, + 1712018, + 1712048, + 1712077, + 1712106, + 1712136, + 1712165, + 1712195, + 1712224, + 1712254, + 1712284, + 1712313, + 1712343, + 1712372, + 1712402, + 1712432, + 1712461, + 1712490, + 1712520, + 1712549, + 1712579, + 1712609, + 1712638, + 1712667, + 1712697, + 1712726, + 1712756, + 1712786, + 1712815, + 1712845, + 1712874, + 1712904, + 1712934, + 1712963, + 1712992, + 1713022, + 1713051, + 1713081, + 1713110, + 1713140, + 1713169, + 1713199, + 1713229, + 1713258, + 1713288, + 1713318, + 1713347, + 1713377, + 1713406, + 1713435, + 1713464, + 1713494, + 1713523, + 1713553, + 1713583, + 1713613, + 1713643, + 1713672, + 1713702, + 1713731, + 1713760, + 1713790, + 1713819, + 1713848, + 1713878, + 1713907, + 1713937, + 1713967, + 1713997, + 1714027, + 1714056, + 1714086, + 1714115, + 1714144, + 1714174, + 1714203, + 1714232, + 1714262, + 1714291, + 1714321, + 1714351, + 1714381, + 1714410, + 1714440, + 1714469, + 1714499, + 1714528, + 1714558, + 1714587, + 1714616, + 1714646, + 1714675, + 1714705, + 1714735, + 1714764, + 1714794, + 1714824, + 1714853, + 1714883, + 1714912, + 1714942, + 1714971, + 1715001, + 1715030, + 1715059, + 1715089, + 1715118, + 1715148, + 1715177, + 1715207, + 1715237, + 1715266, + 1715296, + 1715326, + 1715355, + 1715385, + 1715414, + 1715444, + 1715473, + 1715502, + 1715532, + 1715561, + 1715591, + 1715620, + 1715650, + 1715680, + 1715710, + 1715739, + 1715769, + 1715798, + 1715828, + 1715857, + 1715886, + 1715916, + 1715945, + 1715975, + 1716004, + 1716034, + 1716064, + 1716093, + 1716123, + 1716153, + 1716182, + 1716212, + 1716241, + 1716270, + 1716300, + 1716329, + 1716359, + 1716388, + 1716418, + 1716447, + 1716477, + 1716507, + 1716536, + 1716566, + 1716595, + 1716625, + 1716654, + 1716684, + 1716713, + 1716742, + 1716772, + 1716801, + 1716831, + 1716861, + 1716891, + 1716920, + 1716950, + 1716979, + 1717009, + 1717038, + 1717068, + 1717097, + 1717127, + 1717156, + 1717186, + 1717215, + 1717244, + 1717274, + 1717304, + 1717333, + 1717363, + 1717393, + 1717422, + 1717452, + 1717481, + 1717511, + 1717540, + 1717569, + 1717599, + 1717628, + 1717658, + 1717687, + 1717717, + 1717747, + 1717777, + 1717806, + 1717836, + 1717865, + 1717894, + 1717924, + 1717953, + 1717982, + 1718012, + 1718042, + 1718071, + 1718101, + 1718131, + 1718161, + 1718190, + 1718220, + 1718249, + 1718279, + 1718308, + 1718337, + 1718366, + 1718396, + 1718426, + 1718455, + 1718485, + 1718515, + 1718544, + 1718574, + 1718604, + 1718633, + 1718662, + 1718692, + 1718721, + 1718751, + 1718780, + 1718809, + 1718839, + 1718869, + 1718898, + 1718928, + 1718958, + 1718987, + 1719017, + 1719046, + 1719076, + 1719105, + 1719135, + 1719164, + 1719194, + 1719223, + 1719253, + 1719282, + 1719312, + 1719341, + 1719371, + 1719401, + 1719430, + 1719460, + 1719489, + 1719519, + 1719549, + 1719578, + 1719607, + 1719637, + 1719666, + 1719695, + 1719725, + 1719755, + 1719784, + 1719814, + 1719844, + 1719874, + 1719903, + 1719933, + 1719962, + 1719991, + 1720020, + 1720050, + 1720079, + 1720109, + 1720138, + 1720168, + 1720198, + 1720228, + 1720258, + 1720287, + 1720317, + 1720346, + 1720375, + 1720404, + 1720434, + 1720463, + 1720493, + 1720522, + 1720552, + 1720582, + 1720612, + 1720642, + 1720671, + 1720700, + 1720730, + 1720759, + 1720788, + 1720818, + 1720847, + 1720877, + 1720906, + 1720936, + 1720966, + 1720996, + 1721025, + 1721055, + 1721084, + 1721114, + 1721143, + 1721172, + 1721202, + 1721231, + 1721261, + 1721290, + 1721320, + 1721350, + 1721379, + 1721409, + 1721438, + 1721468, + 1721498, + 1721527, + 1721556, + 1721586, + 1721615, + 1721645, + 1721675, + 1721704, + 1721733, + 1721763, + 1721792, + 1721822, + 1721852, + 1721881, + 1721911, + 1721941, + 1721970, + 1721999, + 1722029, + 1722058, + 1722088, + 1722117, + 1722146, + 1722176, + 1722206, + 1722235, + 1722265, + 1722295, + 1722324, + 1722354, + 1722383, + 1722413, + 1722442, + 1722472, + 1722501, + 1722530, + 1722560, + 1722590, + 1722619, + 1722649, + 1722679, + 1722708, + 1722738, + 1722768, + 1722797, + 1722826, + 1722855, + 1722885, + 1722914, + 1722944, + 1722973, + 1723003, + 1723033, + 1723062, + 1723092, + 1723122, + 1723151, + 1723181, + 1723210, + 1723240, + 1723269, + 1723298, + 1723328, + 1723357, + 1723387, + 1723416, + 1723446, + 1723476, + 1723505, + 1723535, + 1723565, + 1723594, + 1723624, + 1723653, + 1723683, + 1723712, + 1723741, + 1723771, + 1723801, + 1723830, + 1723859, + 1723889, + 1723919, + 1723949, + 1723978, + 1724008, + 1724037, + 1724067, + 1724096, + 1724125, + 1724155, + 1724184, + 1724213, + 1724243, + 1724273, + 1724303, + 1724332, + 1724362, + 1724392, + 1724421, + 1724451, + 1724480, + 1724509, + 1724538, + 1724568, + 1724597, + 1724627, + 1724657, + 1724686, + 1724716, + 1724746, + 1724776, + 1724805, + 1724835, + 1724864, + 1724893, + 1724923, + 1724952, + 1724981, + 1725011, + 1725041, + 1725070, + 1725100, + 1725130, + 1725159, + 1725188, + 1725218, + 1725248, + 1725277, + 1725306, + 1725336, + 1725365, + 1725395, + 1725425, + 1725454, + 1725484, + 1725513, + 1725543, + 1725573, + 1725602, + 1725632, + 1725661, + 1725691, + 1725720, + 1725750, + 1725779, + 1725809, + 1725838, + 1725868, + 1725897, + 1725927, + 1725956, + 1725986, + 1726015, + 1726045, + 1726075, + 1726104, + 1726134, + 1726163, + 1726192, + 1726222, + 1726251, + 1726281, + 1726310, + 1726340, + 1726370, + 1726399, + 1726429, + 1726459, + 1726489, + 1726518, + 1726547, + 1726576, + 1726606, + 1726635, + 1726665, + 1726694, + 1726724, + 1726753, + 1726783, + 1726813, + 1726843, + 1726873, + 1726902, + 1726931, + 1726960, + 1726990, + 1727019, + 1727048, + 1727078, + 1727107, + 1727137, + 1727167, + 1727197, + 1727227, + 1727256, + 1727286, + 1727315, + 1727345, + 1727374, + 1727403, + 1727432, + 1727462, + 1727492, + 1727521, + 1727551, + 1727581, + 1727610, + 1727640, + 1727670, + 1727699, + 1727728, + 1727758, + 1727787, + 1727817, + 1727846, + 1727876, + 1727905, + 1727935, + 1727964, + 1727994, + 1728024, + 1728053, + 1728083, + 1728112, + 1728142, + 1728171, + 1728201, + 1728230, + 1728260, + 1728289, + 1728319, + 1728348, + 1728378, + 1728407, + 1728437, + 1728467, + 1728496, + 1728526, + 1728555, + 1728585, + 1728614, + 1728644, + 1728673, + 1728702, + 1728732, + 1728761, + 1728791, + 1728821, + 1728850, + 1728880, + 1728910, + 1728939, + 1728969, + 1728998, + 1729028, + 1729057, + 1729086, + 1729116, + 1729145, + 1729175, + 1729204, + 1729234, + 1729264, + 1729294, + 1729323, + 1729353, + 1729382, + 1729412, + 1729441, + 1729470, + 1729500, + 1729529, + 1729559, + 1729588, + 1729618, + 1729648, + 1729678, + 1729707, + 1729737, + 1729766, + 1729795, + 1729825, + 1729854, + 1729884, + 1729913, + 1729943, + 1729972, + 1730002, + 1730031, + 1730061, + 1730091, + 1730120, + 1730150, + 1730179, + 1730209, + 1730238, + 1730268, + 1730297, + 1730327, + 1730356, + 1730386, + 1730415, + 1730445, + 1730474, + 1730504, + 1730534, + 1730564, + 1730593, + 1730623, + 1730652, + 1730681, + 1730711, + 1730740, + 1730769, + 1730799, + 1730828, + 1730858, + 1730888, + 1730918, + 1730947, + 1730977, + 1731006, + 1731036, + 1731065, + 1731094, + 1731124, + 1731153, + 1731183, + 1731212, + 1731242, + 1731272, + 1731302, + 1731331, + 1731361, + 1731390, + 1731420, + 1731449, + 1731478, + 1731508, + 1731537, + 1731567, + 1731596, + 1731626, + 1731656, + 1731685, + 1731715, + 1731745, + 1731774, + 1731804, + 1731833, + 1731862, + 1731892, + 1731921, + 1731951, + 1731980, + 1732010, + 1732039, + 1732069, + 1732099, + 1732128, + 1732158, + 1732187, + 1732217, + 1732246, + 1732276, + 1732305, + 1732335, + 1732364, + 1732394, + 1732423, + 1732453, + 1732482, + 1732512, + 1732542, + 1732571, + 1732601, + 1732630, + 1732660, + 1732690, + 1732719, + 1732748, + 1732778, + 1732807, + 1732837, + 1732866, + 1732896, + 1732925, + 1732955, + 1732985, + 1733015, + 1733044, + 1733074, + 1733103, + 1733132, + 1733162, + 1733191, + 1733220, + 1733250, + 1733279, + 1733309, + 1733339, + 1733369, + 1733399, + 1733428, + 1733458, + 1733487, + 1733516, + 1733546, + 1733575, + 1733604, + 1733634, + 1733663, + 1733693, + 1733723, + 1733753, + 1733782, + 1733812, + 1733842, + 1733871, + 1733900, + 1733930, + 1733959, + 1733988, + 1734018, + 1734047, + 1734077, + 1734107, + 1734136, + 1734166, + 1734196, + 1734225, + 1734255, + 1734284, + 1734314, + 1734343, + 1734372, + 1734402, + 1734431, + 1734461, + 1734491, + 1734520, + 1734550, + 1734579, + 1734609, + 1734639, + 1734668, + 1734698, + 1734727, + 1734757, + 1734786, + 1734815, + 1734845, + 1734875, + 1734904, + 1734933, + 1734963, + 1734993, + 1735022, + 1735052, + 1735082, + 1735111, + 1735141, + 1735170, + 1735200, + 1735229, + 1735258, + 1735288, + 1735317, + 1735347, + 1735376, + 1735406, + 1735436, + 1735465, + 1735495, + 1735525, + 1735554, + 1735584, + 1735613, + 1735642, + 1735672, + 1735701, + 1735731, + 1735760, + 1735790, + 1735819, + 1735849, + 1735879, + 1735909, + 1735938, + 1735968, + 1735997, + 1736026, + 1736056, + 1736085, + 1736114, + 1736144, + 1736174, + 1736203, + 1736233, + 1736263, + 1736293, + 1736322, + 1736351, + 1736381, + 1736410, + 1736440, + 1736469, + 1736498, + 1736528, + 1736557, + 1736587, + 1736617, + 1736646, + 1736676, + 1736706, + 1736735, + 1736764, + 1736794, + 1736824, + 1736853, + 1736882, + 1736912, + 1736941, + 1736971, + 1737000, + 1737030, + 1737060, + 1737089, + 1737119, + 1737149, + 1737178, + 1737208, + 1737237, + 1737267, + 1737296, + 1737325, + 1737355, + 1737384, + 1737414, + 1737443, + 1737473, + 1737503, + 1737533, + 1737562, + 1737592, + 1737621, + 1737651, + 1737680, + 1737709, + 1737739, + 1737768, + 1737798, + 1737827, + 1737857, + 1737887, + 1737917, + 1737946, + 1737976, + 1738005, + 1738035, + 1738064, + 1738093, + 1738122, + 1738152, + 1738182, + 1738211, + 1738241, + 1738271, + 1738300, + 1738330, + 1738360, + 1738389, + 1738418, + 1738448, + 1738477, + 1738507, + 1738536, + 1738566, + 1738595, + 1738625, + 1738654, + 1738684, + 1738714, + 1738743, + 1738773, + 1738802, + 1738832, + 1738861, + 1738891, + 1738920, + 1738950, + 1738979, + 1739009, + 1739038, + 1739068, + 1739097, + 1739127, + 1739156, + 1739186, + 1739216, + 1739246, + 1739275, + 1739304, + 1739334, + 1739363, + 1739392, + 1739422, + 1739451, + 1739481, + 1739510, + 1739540, + 1739570, + 1739600, + 1739630, + 1739659, + 1739689, + 1739718, + 1739747, + 1739776, + 1739806, + 1739835, + 1739865, + 1739894, + 1739924, + 1739954, + 1739984, + 1740014, + 1740043, + 1740072, + 1740102, + 1740131, + 1740160, + 1740190, + 1740219, + 1740248, + 1740278, + 1740308, + 1740338, + 1740368, + 1740397, + 1740427, + 1740456, + 1740486, + 1740515, + 1740544, + 1740574, + 1740603, + 1740633, + 1740662, + 1740692, + 1740722, + 1740751, + 1740781, + 1740811, + 1740840, + 1740870, + 1740899, + 1740928, + 1740958, + 1740987, + 1741017, + 1741046, + 1741076, + 1741105, + 1741135, + 1741165, + 1741194, + 1741224, + 1741253, + 1741283, + 1741312, + 1741342, + 1741371, + 1741401, + 1741430, + 1741460, + 1741489, + 1741519, + 1741548, + 1741578, + 1741608, + 1741637, + 1741667, + 1741697, + 1741726, + 1741756, + 1741785, + 1741814, + 1741844, + 1741873, + 1741902, + 1741932, + 1741962, + 1741991, + 1742021, + 1742051, + 1742081, + 1742110, + 1742140, + 1742169, + 1742198, + 1742228, + 1742257, + 1742286, + 1742316, + 1742345, + 1742375, + 1742405, + 1742435, + 1742464, + 1742494, + 1742524, + 1742553, + 1742582, + 1742612, + 1742641, + 1742670, + 1742700, + 1742729, + 1742759, + 1742789, + 1742818, + 1742848, + 1742878, + 1742907, + 1742937, + 1742966, + 1742996, + 1743025, + 1743054, + 1743084, + 1743113, + 1743143, + 1743172, + 1743202, + 1743232, + 1743261, + 1743291, + 1743321, + 1743350, + 1743380, + 1743409, + 1743438, + 1743468, + 1743497, + 1743527, + 1743556, + 1743586, + 1743615, + 1743645, + 1743675, + 1743704, + 1743734, + 1743763, + 1743793, + 1743823, + 1743852, + 1743881, + 1743911, + 1743940, + 1743969, + 1743999, + 1744029, + 1744059, + 1744088, + 1744118, + 1744148, + 1744177, + 1744207, + 1744236, + 1744265, + 1744295, + 1744324, + 1744353, + 1744383, + 1744413, + 1744442, + 1744472, + 1744502, + 1744531, + 1744561, + 1744590, + 1744620, + 1744649, + 1744678, + 1744708, + 1744737, + 1744767, + 1744797, + 1744827, + 1744856, + 1744885, + 1744915, + 1744945, + 1744974, + 1745004, + 1745033, + 1745063, + 1745092, + 1745121, + 1745151, + 1745181, + 1745210, + 1745239, + 1745269, + 1745299, + 1745328, + 1745358, + 1745388, + 1745417, + 1745447, + 1745476, + 1745506, + 1745535, + 1745564, + 1745594, + 1745623, + 1745653, + 1745682, + 1745712, + 1745742, + 1745771, + 1745801, + 1745831, + 1745860, + 1745890, + 1745919, + 1745948, + 1745978, + 1746007, + 1746037, + 1746066, + 1746096, + 1746125, + 1746155, + 1746185, + 1746215, + 1746244, + 1746274, + 1746303, + 1746332, + 1746362, + 1746391, + 1746420, + 1746450, + 1746479, + 1746509, + 1746539, + 1746569, + 1746599, + 1746628, + 1746658, + 1746687, + 1746716, + 1746746, + 1746775, + 1746804, + 1746834, + 1746863, + 1746893, + 1746923, + 1746953, + 1746983, + 1747012, + 1747042, + 1747071, + 1747100, + 1747130, + 1747159, + 1747188, + 1747218, + 1747248, + 1747277, + 1747307, + 1747336, + 1747366, + 1747396, + 1747425, + 1747455, + 1747484, + 1747514, + 1747543, + 1747573, + 1747602, + 1747632, + 1747661, + 1747691, + 1747720, + 1747750, + 1747780, + 1747809, + 1747839, + 1747868, + 1747898, + 1747927, + 1747957, + 1747986, + 1748016, + 1748045, + 1748074, + 1748104, + 1748134, + 1748163, + 1748193, + 1748223, + 1748252, + 1748282, + 1748312, + 1748341, + 1748370, + 1748400, + 1748429, + 1748458, + 1748488, + 1748517, + 1748547, + 1748576, + 1748606, + 1748636, + 1748666, + 1748696, + 1748725, + 1748755, + 1748784, + 1748813, + 1748842, + 1748872 + ], + + "babylonYmPd": [ + -314.01, + -314.02, + -314.03, + -314.04, + -314.05, + -314.06, + -314.07, + -314.08, + -314.09, + -314.1, + -314.11, + -314.12, + -313.01, + -313.02, + -313.03, + -313.04, + -313.05, + -313.06, + -313.07, + -313.08, + -313.09, + -313.1, + -313.11, + -313.12, + -312.01, + -312.02, + -312.03, + -312.04, + -312.05, + -312.06, + -312.07, + -312.08, + -312.09, + -312.1, + -312.11, + -312.12, + -312.14, + -311.01, + -311.02, + -311.03, + -311.04, + -311.05, + -311.06, + -311.07, + -311.08, + -311.09, + -311.1, + -311.11, + -311.12, + -310.01, + -310.02, + -310.03, + -310.04, + -310.05, + -310.06, + -310.07, + -310.08, + -310.09, + -310.1, + -310.11, + -310.12, + -309.01, + -309.02, + -309.03, + -309.04, + -309.05, + -309.06, + -309.13, + -309.07, + -309.08, + -309.09, + -309.1, + -309.11, + -309.12, + -308.01, + -308.02, + -308.03, + -308.04, + -308.05, + -308.06, + -308.07, + -308.08, + -308.09, + -308.1, + -308.11, + -308.12, + -307.01, + -307.02, + -307.03, + -307.04, + -307.05, + -307.06, + -307.07, + -307.08, + -307.09, + -307.1, + -307.11, + -307.12, + -307.14, + -306.01, + -306.02, + -306.03, + -306.04, + -306.05, + -306.06, + -306.07, + -306.08, + -306.09, + -306.1, + -306.11, + -306.12, + -305.01, + -305.02, + -305.03, + -305.04, + -305.05, + -305.06, + -305.07, + -305.08, + -305.09, + -305.1, + -305.11, + -305.12, + -304.01, + -304.02, + -304.03, + -304.04, + -304.05, + -304.06, + -304.13, + -304.07, + -304.08, + -304.09, + -304.1, + -304.11, + -304.12, + -303.01, + -303.02, + -303.03, + -303.04, + -303.05, + -303.06, + -303.07, + -303.08, + -303.09, + -303.1, + -303.11, + -303.12, + -302.01, + -302.02, + -302.03, + -302.04, + -302.05, + -302.06, + -302.07, + -302.08, + -302.09, + -302.1, + -302.11, + -302.12, + -302.14, + -301.01, + -301.02, + -301.03, + -301.04, + -301.05, + -301.06, + -301.07, + -301.08, + -301.09, + -301.1, + -301.11, + -301.12, + -300.01, + -300.02, + -300.03, + -300.04, + -300.05, + -300.06, + -300.07, + -300.08, + -300.09, + -300.1, + -300.11, + -300.12, + -299.01, + -299.02, + -299.03, + -299.04, + -299.05, + -299.06, + -299.13, + -299.07, + -299.08, + -299.09, + -299.1, + -299.11, + -299.12, + -298.01, + -298.02, + -298.03, + -298.04, + -298.05, + -298.06, + -298.07, + -298.08, + -298.09, + -298.1, + -298.11, + -298.12, + -297.01, + -297.02, + -297.03, + -297.04, + -297.05, + -297.06, + -297.07, + -297.08, + -297.09, + -297.1, + -297.11, + -297.12, + -296.01, + -296.02, + -296.03, + -296.04, + -296.05, + -296.06, + -296.07, + -296.08, + -296.09, + -296.1, + -296.11, + -296.12, + -295.01, + -295.02, + -295.03, + -295.04, + -295.05, + -295.06, + -295.13, + -295.07, + -295.08, + -295.09, + -295.1, + -295.11, + -295.12, + -294.01, + -294.02, + -294.03, + -294.04, + -294.05, + -294.06, + -294.07, + -294.08, + -294.09, + -294.1, + -294.11, + -294.12, + -294.14, + -293.01, + -293.02, + -293.03, + -293.04, + -293.05, + -293.06, + -293.07, + -293.08, + -293.09, + -293.1, + -293.11, + -293.12, + -292.01, + -292.02, + -292.03, + -292.04, + -292.05, + -292.06, + -292.07, + -292.08, + -292.09, + -292.1, + -292.11, + -292.12, + -291.01, + -291.02, + -291.03, + -291.04, + -291.05, + -291.06, + -291.13, + -291.07, + -291.08, + -291.09, + -291.1, + -291.11, + -291.12, + -290.01, + -290.02, + -290.03, + -290.04, + -290.05, + -290.06, + -290.07, + -290.08, + -290.09, + -290.1, + -290.11, + -290.12, + -289.01, + -289.02, + -289.03, + -289.04, + -289.05, + -289.06, + -289.07, + -289.08, + -289.09, + -289.1, + -289.11, + -289.12, + -288.01, + -288.02, + -288.03, + -288.04, + -288.05, + -288.06, + -288.13, + -288.07, + -288.08, + -288.09, + -288.1, + -288.11, + -288.12, + -287.01, + -287.02, + -287.03, + -287.04, + -287.05, + -287.06, + -287.07, + -287.08, + -287.09, + -287.1, + -287.11, + -287.12, + -286.01, + -286.02, + -286.03, + -286.04, + -286.05, + -286.06, + -286.13, + -286.07, + -286.08, + -286.09, + -286.1, + -286.11, + -286.12, + -285.01, + -285.02, + -285.03, + -285.04, + -285.05, + -285.06, + -285.07, + -285.08, + -285.09, + -285.1, + -285.11, + -285.12, + -284.01, + -284.02, + -284.03, + -284.04, + -284.05, + -284.06, + -284.13, + -284.07, + -284.08, + -284.09, + -284.1, + -284.11, + -284.12, + -283.01, + -283.02, + -283.03, + -283.04, + -283.05, + -283.06, + -283.07, + -283.08, + -283.09, + -283.1, + -283.11, + -283.12, + -282.01, + -282.02, + -282.03, + -282.04, + -282.05, + -282.06, + -282.07, + -282.08, + -282.09, + -282.1, + -282.11, + -282.12, + -282.14, + -281.01, + -281.02, + -281.03, + -281.04, + -281.05, + -281.06, + -281.07, + -281.08, + -281.09, + -281.1, + -281.11, + -281.12, + -280.01, + -280.02, + -280.03, + -280.04, + -280.05, + -280.06, + -280.07, + -280.08, + -280.09, + -280.1, + -280.11, + -280.12, + -279.01, + -279.02, + -279.03, + -279.04, + -279.05, + -279.06, + -279.07, + -279.08, + -279.09, + -279.1, + -279.11, + -279.12, + -279.14, + -278.01, + -278.02, + -278.03, + -278.04, + -278.05, + -278.06, + -278.07, + -278.08, + -278.09, + -278.1, + -278.11, + -278.12, + -277.01, + -277.02, + -277.03, + -277.04, + -277.05, + -277.06, + -277.07, + -277.08, + -277.09, + -277.1, + -277.11, + -277.12, + -276.01, + -276.02, + -276.03, + -276.04, + -276.05, + -276.06, + -276.07, + -276.08, + -276.09, + -276.1, + -276.11, + -276.12, + -276.14, + -275.01, + -275.02, + -275.03, + -275.04, + -275.05, + -275.06, + -275.07, + -275.08, + -275.09, + -275.1, + -275.11, + -275.12, + -274.01, + -274.02, + -274.03, + -274.04, + -274.05, + -274.06, + -274.07, + -274.08, + -274.09, + -274.1, + -274.11, + -274.12, + -273.01, + -273.02, + -273.03, + -273.04, + -273.05, + -273.06, + -273.07, + -273.08, + -273.09, + -273.1, + -273.11, + -273.12, + -272.01, + -272.02, + -272.03, + -272.04, + -272.05, + -272.06, + -272.13, + -272.07, + -272.08, + -272.09, + -272.1, + -272.11, + -272.12, + -271.01, + -271.02, + -271.03, + -271.04, + -271.05, + -271.06, + -271.07, + -271.08, + -271.09, + -271.1, + -271.11, + -271.12, + -270.01, + -270.02, + -270.03, + -270.04, + -270.05, + -270.06, + -270.07, + -270.08, + -270.09, + -270.1, + -270.11, + -270.12, + -270.14, + -269.01, + -269.02, + -269.03, + -269.04, + -269.05, + -269.06, + -269.07, + -269.08, + -269.09, + -269.1, + -269.11, + -269.12, + -268.01, + -268.02, + -268.03, + -268.04, + -268.05, + -268.06, + -268.07, + -268.08, + -268.09, + -268.1, + -268.11, + -268.12, + -267.01, + -267.02, + -267.03, + -267.04, + -267.05, + -267.06, + -267.07, + -267.08, + -267.09, + -267.1, + -267.11, + -267.12, + -267.14, + -266.01, + -266.02, + -266.03, + -266.04, + -266.05, + -266.06, + -266.07, + -266.08, + -266.09, + -266.1, + -266.11, + -266.12, + -265.01, + -265.02, + -265.03, + -265.04, + -265.05, + -265.06, + -265.07, + -265.08, + -265.09, + -265.1, + -265.11, + -265.12, + -265.14, + -264.01, + -264.02, + -264.03, + -264.04, + -264.05, + -264.06, + -264.07, + -264.08, + -264.09, + -264.1, + -264.11, + -264.12, + -263.01, + -263.02, + -263.03, + -263.04, + -263.05, + -263.06, + -263.07, + -263.08, + -263.09, + -263.1, + -263.11, + -263.12, + -262.01, + -262.02, + -262.03, + -262.04, + -262.05, + -262.06, + -262.13, + -262.07, + -262.08, + -262.09, + -262.1, + -262.11, + -262.12, + -261.01, + -261.02, + -261.03, + -261.04, + -261.05, + -261.06, + -261.07, + -261.08, + -261.09, + -261.1, + -261.11, + -261.12, + -260.01, + -260.02, + -260.03, + -260.04, + -260.05, + -260.06, + -260.07, + -260.08, + -260.09, + -260.1, + -260.11, + -260.12, + -260.14, + -259.01, + -259.02, + -259.03, + -259.04, + -259.05, + -259.06, + -259.07, + -259.08, + -259.09, + -259.1, + -259.11, + -259.12, + -258.01, + -258.02, + -258.03, + -258.04, + -258.05, + -258.06, + -258.07, + -258.08, + -258.09, + -258.1, + -258.11, + -258.12, + -257.01, + -257.02, + -257.03, + -257.04, + -257.05, + -257.06, + -257.07, + -257.08, + -257.09, + -257.1, + -257.11, + -257.12, + -257.14, + -256.01, + -256.02, + -256.03, + -256.04, + -256.05, + -256.06, + -256.07, + -256.08, + -256.09, + -256.1, + -256.11, + -256.12, + -255.01, + -255.02, + -255.03, + -255.04, + -255.05, + -255.06, + -255.07, + -255.08, + -255.09, + -255.1, + -255.11, + -255.12, + -254.01, + -254.02, + -254.03, + -254.04, + -254.05, + -254.06, + -254.07, + -254.08, + -254.09, + -254.1, + -254.11, + -254.12, + -253.01, + -253.02, + -253.03, + -253.04, + -253.05, + -253.06, + -253.07, + -253.08, + -253.09, + -253.1, + -253.11, + -253.12, + -252.01, + -252.02, + -252.03, + -252.04, + -252.05, + -252.06, + -252.13, + -252.07, + -252.08, + -252.09, + -252.1, + -252.11, + -252.12, + -251.01, + -251.02, + -251.03, + -251.04, + -251.05, + -251.06, + -251.07, + -251.08, + -251.09, + -251.1, + -251.11, + -251.12, + -251.14, + -250.01, + -250.02, + -250.03, + -250.04, + -250.05, + -250.06, + -250.07, + -250.08, + -250.09, + -250.1, + -250.11, + -250.12, + -249.01, + -249.02, + -249.03, + -249.04, + -249.05, + -249.06, + -249.07, + -249.08, + -249.09, + -249.1, + -249.11, + -249.12, + -248.01, + -248.02, + -248.03, + -248.04, + -248.05, + -248.06, + -248.07, + -248.08, + -248.09, + -248.1, + -248.11, + -248.12, + -248.14, + -247.01, + -247.02, + -247.03, + -247.04, + -247.05, + -247.06, + -247.07, + -247.08, + -247.09, + -247.1, + -247.11, + -247.12, + -246.01, + -246.02, + -246.03, + -246.04, + -246.05, + -246.06, + -246.07, + -246.08, + -246.09, + -246.1, + -246.11, + -246.12, + -245.01, + -245.02, + -245.03, + -245.04, + -245.05, + -245.06, + -245.07, + -245.08, + -245.09, + -245.1, + -245.11, + -245.12, + -245.14, + -244.01, + -244.02, + -244.03, + -244.04, + -244.05, + -244.06, + -244.07, + -244.08, + -244.09, + -244.1, + -244.11, + -244.12, + -243.01, + -243.02, + -243.03, + -243.04, + -243.05, + -243.06, + -243.07, + -243.08, + -243.09, + -243.1, + -243.11, + -243.12, + -243.14, + -242.01, + -242.02, + -242.03, + -242.04, + -242.05, + -242.06, + -242.07, + -242.08, + -242.09, + -242.1, + -242.11, + -242.12, + -241.01, + -241.02, + -241.03, + -241.04, + -241.05, + -241.06, + -241.07, + -241.08, + -241.09, + -241.1, + -241.11, + -241.12, + -241.14, + -240.01, + -240.02, + -240.03, + -240.04, + -240.05, + -240.06, + -240.07, + -240.08, + -240.09, + -240.1, + -240.11, + -240.12, + -239.01, + -239.02, + -239.03, + -239.04, + -239.05, + -239.06, + -239.07, + -239.08, + -239.09, + -239.1, + -239.11, + -239.12, + -238.01, + -238.02, + -238.03, + -238.04, + -238.05, + -238.06, + -238.07, + -238.08, + -238.09, + -238.1, + -238.11, + -238.12, + -238.14, + -237.01, + -237.02, + -237.03, + -237.04, + -237.05, + -237.06, + -237.07, + -237.08, + -237.09, + -237.1, + -237.11, + -237.12, + -236.01, + -236.02, + -236.03, + -236.04, + -236.05, + -236.06, + -236.07, + -236.08, + -236.09, + -236.1, + -236.11, + -236.12, + -235.01, + -235.02, + -235.03, + -235.04, + -235.05, + -235.06, + -235.07, + -235.08, + -235.09, + -235.1, + -235.11, + -235.12, + -234.01, + -234.02, + -234.03, + -234.04, + -234.05, + -234.06, + -234.13, + -234.07, + -234.08, + -234.09, + -234.1, + -234.11, + -234.12, + -233.01, + -233.02, + -233.03, + -233.04, + -233.05, + -233.06, + -233.07, + -233.08, + -233.09, + -233.1, + -233.11, + -233.12, + -232.01, + -232.02, + -232.03, + -232.04, + -232.05, + -232.06, + -232.07, + -232.08, + -232.09, + -232.1, + -232.11, + -232.12, + -232.14, + -231.01, + -231.02, + -231.03, + -231.04, + -231.05, + -231.06, + -231.07, + -231.08, + -231.09, + -231.1, + -231.11, + -231.12, + -230.01, + -230.02, + -230.03, + -230.04, + -230.05, + -230.06, + -230.07, + -230.08, + -230.09, + -230.1, + -230.11, + -230.12, + -229.01, + -229.02, + -229.03, + -229.04, + -229.05, + -229.06, + -229.07, + -229.08, + -229.09, + -229.1, + -229.11, + -229.12, + -229.14, + -228.01, + -228.02, + -228.03, + -228.04, + -228.05, + -228.06, + -228.07, + -228.08, + -228.09, + -228.1, + -228.11, + -228.12, + -227.01, + -227.02, + -227.03, + -227.04, + -227.05, + -227.06, + -227.07, + -227.08, + -227.09, + -227.1, + -227.11, + -227.12, + -226.01, + -226.02, + -226.03, + -226.04, + -226.05, + -226.06, + -226.07, + -226.08, + -226.09, + -226.1, + -226.11, + -226.12, + -225.01, + -225.02, + -225.03, + -225.04, + -225.05, + -225.06, + -225.13, + -225.07, + -225.08, + -225.09, + -225.1, + -225.11, + -225.12, + -224.01, + -224.02, + -224.03, + -224.04, + -224.05, + -224.06, + -224.07, + -224.08, + -224.09, + -224.1, + -224.11, + -224.12, + -224.14, + -223.01, + -223.02, + -223.03, + -223.04, + -223.05, + -223.06, + -223.07, + -223.08, + -223.09, + -223.1, + -223.11, + -223.12, + -222.01, + -222.02, + -222.03, + -222.04, + -222.05, + -222.06, + -222.07, + -222.08, + -222.09, + -222.1, + -222.11, + -222.12, + -221.01, + -221.02, + -221.03, + -221.04, + -221.05, + -221.06, + -221.07, + -221.08, + -221.09, + -221.1, + -221.11, + -221.12, + -221.14, + -220.01, + -220.02, + -220.03, + -220.04, + -220.05, + -220.06, + -220.07, + -220.08, + -220.09, + -220.1, + -220.11, + -220.12, + -219.01, + -219.02, + -219.03, + -219.04, + -219.05, + -219.06, + -219.07, + -219.08, + -219.09, + -219.1, + -219.11, + -219.12, + -218.01, + -218.02, + -218.03, + -218.04, + -218.05, + -218.06, + -218.13, + -218.07, + -218.08, + -218.09, + -218.1, + -218.11, + -218.12, + -217.01, + -217.02, + -217.03, + -217.04, + -217.05, + -217.06, + -217.07, + -217.08, + -217.09, + -217.1, + -217.11, + -217.12, + -216.01, + -216.02, + -216.03, + -216.04, + -216.05, + -216.06, + -216.07, + -216.08, + -216.09, + -216.1, + -216.11, + -216.12, + -215.01, + -215.02, + -215.03, + -215.04, + -215.05, + -215.06, + -215.13, + -215.07, + -215.08, + -215.09, + -215.1, + -215.11, + -215.12, + -214.01, + -214.02, + -214.03, + -214.04, + -214.05, + -214.06, + -214.07, + -214.08, + -214.09, + -214.1, + -214.11, + -214.12, + -213.01, + -213.02, + -213.03, + -213.04, + -213.05, + -213.06, + -213.07, + -213.08, + -213.09, + -213.1, + -213.11, + -213.12, + -213.14, + -212.01, + -212.02, + -212.03, + -212.04, + -212.05, + -212.06, + -212.07, + -212.08, + -212.09, + -212.1, + -212.11, + -212.12, + -211.01, + -211.02, + -211.03, + -211.04, + -211.05, + -211.06, + -211.07, + -211.08, + -211.09, + -211.1, + -211.11, + -211.12, + -210.01, + -210.02, + -210.03, + -210.04, + -210.05, + -210.06, + -210.07, + -210.08, + -210.09, + -210.1, + -210.11, + -210.12, + -210.14, + -209.01, + -209.02, + -209.03, + -209.04, + -209.05, + -209.06, + -209.07, + -209.08, + -209.09, + -209.1, + -209.11, + -209.12, + -208.01, + -208.02, + -208.03, + -208.04, + -208.05, + -208.06, + -208.07, + -208.08, + -208.09, + -208.1, + -208.11, + -208.12, + -207.01, + -207.02, + -207.03, + -207.04, + -207.05, + -207.06, + -207.13, + -207.07, + -207.08, + -207.09, + -207.1, + -207.11, + -207.12, + -206.01, + -206.02, + -206.03, + -206.04, + -206.05, + -206.06, + -206.07, + -206.08, + -206.09, + -206.1, + -206.11, + -206.12, + -205.01, + -205.02, + -205.03, + -205.04, + -205.05, + -205.06, + -205.07, + -205.08, + -205.09, + -205.1, + -205.11, + -205.12, + -205.14, + -204.01, + -204.02, + -204.03, + -204.04, + -204.05, + -204.06, + -204.07, + -204.08, + -204.09, + -204.1, + -204.11, + -204.12, + -203.01, + -203.02, + -203.03, + -203.04, + -203.05, + -203.06, + -203.07, + -203.08, + -203.09, + -203.1, + -203.11, + -203.12, + -202.01, + -202.02, + -202.03, + -202.04, + -202.05, + -202.06, + -202.07, + -202.08, + -202.09, + -202.1, + -202.11, + -202.12, + -202.14, + -201.01, + -201.02, + -201.03, + -201.04, + -201.05, + -201.06, + -201.07, + -201.08, + -201.09, + -201.1, + -201.11, + -201.12, + -200.01, + -200.02, + -200.03, + -200.04, + -200.05, + -200.06, + -200.07, + -200.08, + -200.09, + -200.1, + -200.11, + -200.12, + -199.01, + -199.02, + -199.03, + -199.04, + -199.05, + -199.06, + -199.13, + -199.07, + -199.08, + -199.09, + -199.1, + -199.11, + -199.12, + -198.01, + -198.02, + -198.03, + -198.04, + -198.05, + -198.06, + -198.07, + -198.08, + -198.09, + -198.1, + -198.11, + -198.12, + -197.01, + -197.02, + -197.03, + -197.04, + -197.05, + -197.06, + -197.07, + -197.08, + -197.09, + -197.1, + -197.11, + -197.12, + -197.14, + -196.01, + -196.02, + -196.03, + -196.04, + -196.05, + -196.06, + -196.07, + -196.08, + -196.09, + -196.1, + -196.11, + -196.12, + -195.01, + -195.02, + -195.03, + -195.04, + -195.05, + -195.06, + -195.07, + -195.08, + -195.09, + -195.1, + -195.11, + -195.12, + -194.01, + -194.02, + -194.03, + -194.04, + -194.05, + -194.06, + -194.07, + -194.08, + -194.09, + -194.1, + -194.11, + -194.12, + -194.14, + -193.01, + -193.02, + -193.03, + -193.04, + -193.05, + -193.06, + -193.07, + -193.08, + -193.09, + -193.1, + -193.11, + -193.12, + -192.01, + -192.02, + -192.03, + -192.04, + -192.05, + -192.06, + -192.07, + -192.08, + -192.09, + -192.1, + -192.11, + -192.12, + -191.01, + -191.02, + -191.03, + -191.04, + -191.05, + -191.06, + -191.13, + -191.07, + -191.08, + -191.09, + -191.1, + -191.11, + -191.12, + -190.01, + -190.02, + -190.03, + -190.04, + -190.05, + -190.06, + -190.07, + -190.08, + -190.09, + -190.1, + -190.11, + -190.12, + -189.01, + -189.02, + -189.03, + -189.04, + -189.05, + -189.06, + -189.07, + -189.08, + -189.09, + -189.1, + -189.11, + -189.12, + -188.01, + -188.02, + -188.03, + -188.04, + -188.05, + -188.06, + -188.07, + -188.08, + -188.09, + -188.1, + -188.11, + -188.12, + -188.14, + -187.01, + -187.02, + -187.03, + -187.04, + -187.05, + -187.06, + -187.07, + -187.08, + -187.09, + -187.1, + -187.11, + -187.12, + -186.01, + -186.02, + -186.03, + -186.04, + -186.05, + -186.06, + -186.07, + -186.08, + -186.09, + -186.1, + -186.11, + -186.12, + -186.14, + -185.01, + -185.02, + -185.03, + -185.04, + -185.05, + -185.06, + -185.07, + -185.08, + -185.09, + -185.1, + -185.11, + -185.12, + -184.01, + -184.02, + -184.03, + -184.04, + -184.05, + -184.06, + -184.07, + -184.08, + -184.09, + -184.1, + -184.11, + -184.12, + -183.01, + -183.02, + -183.03, + -183.04, + -183.05, + -183.06, + -183.07, + -183.08, + -183.09, + -183.1, + -183.11, + -183.12, + -183.14, + -182.01, + -182.02, + -182.03, + -182.04, + -182.05, + -182.06, + -182.07, + -182.08, + -182.09, + -182.1, + -182.11, + -182.12, + -181.01, + -181.02, + -181.03, + -181.04, + -181.05, + -181.06, + -181.07, + -181.08, + -181.09, + -181.1, + -181.11, + -181.12, + -181.14, + -180.01, + -180.02, + -180.03, + -180.04, + -180.05, + -180.06, + -180.07, + -180.08, + -180.09, + -180.1, + -180.11, + -180.12, + -179.01, + -179.02, + -179.03, + -179.04, + -179.05, + -179.06, + -179.07, + -179.08, + -179.09, + -179.1, + -179.11, + -179.12, + -178.01, + -178.02, + -178.03, + -178.04, + -178.05, + -178.06, + -178.07, + -178.08, + -178.09, + -178.1, + -178.11, + -178.12, + -178.14, + -177.01, + -177.02, + -177.03, + -177.04, + -177.05, + -177.06, + -177.07, + -177.08, + -177.09, + -177.1, + -177.11, + -177.12, + -176.01, + -176.02, + -176.03, + -176.04, + -176.05, + -176.06, + -176.07, + -176.08, + -176.09, + -176.1, + -176.11, + -176.12, + -175.01, + -175.02, + -175.03, + -175.04, + -175.05, + -175.06, + -175.07, + -175.08, + -175.09, + -175.1, + -175.11, + -175.12, + -175.14, + -174.01, + -174.02, + -174.03, + -174.04, + -174.05, + -174.06, + -174.07, + -174.08, + -174.09, + -174.1, + -174.11, + -174.12, + -173.01, + -173.02, + -173.03, + -173.04, + -173.05, + -173.06, + -173.07, + -173.08, + -173.09, + -173.1, + -173.11, + -173.12, + -172.01, + -172.02, + -172.03, + -172.04, + -172.05, + -172.06, + -172.13, + -172.07, + -172.08, + -172.09, + -172.1, + -172.11, + -172.12, + -171.01, + -171.02, + -171.03, + -171.04, + -171.05, + -171.06, + -171.07, + -171.08, + -171.09, + -171.1, + -171.11, + -171.12, + -170.01, + -170.02, + -170.03, + -170.04, + -170.05, + -170.06, + -170.07, + -170.08, + -170.09, + -170.1, + -170.11, + -170.12, + -170.14, + -169.01, + -169.02, + -169.03, + -169.04, + -169.05, + -169.06, + -169.07, + -169.08, + -169.09, + -169.1, + -169.11, + -169.12, + -168.01, + -168.02, + -168.03, + -168.04, + -168.05, + -168.06, + -168.07, + -168.08, + -168.09, + -168.1, + -168.11, + -168.12, + -167.01, + -167.02, + -167.03, + -167.04, + -167.05, + -167.06, + -167.07, + -167.08, + -167.09, + -167.1, + -167.11, + -167.12, + -167.14, + -166.01, + -166.02, + -166.03, + -166.04, + -166.05, + -166.06, + -166.07, + -166.08, + -166.09, + -166.1, + -166.11, + -166.12, + -165.01, + -165.02, + -165.03, + -165.04, + -165.05, + -165.06, + -165.07, + -165.08, + -165.09, + -165.1, + -165.11, + -165.12, + -164.01, + -164.02, + -164.03, + -164.04, + -164.05, + -164.06, + -164.07, + -164.08, + -164.09, + -164.1, + -164.11, + -164.12, + -164.14, + -163.01, + -163.02, + -163.03, + -163.04, + -163.05, + -163.06, + -163.07, + -163.08, + -163.09, + -163.1, + -163.11, + -163.12, + -162.01, + -162.02, + -162.03, + -162.04, + -162.05, + -162.06, + -162.07, + -162.08, + -162.09, + -162.1, + -162.11, + -162.12, + -162.14, + -161.01, + -161.02, + -161.03, + -161.04, + -161.05, + -161.06, + -161.07, + -161.08, + -161.09, + -161.1, + -161.11, + -161.12, + -160.01, + -160.02, + -160.03, + -160.04, + -160.05, + -160.06, + -160.07, + -160.08, + -160.09, + -160.1, + -160.11, + -160.12, + -159.01, + -159.02, + -159.03, + -159.04, + -159.05, + -159.06, + -159.07, + -159.08, + -159.09, + -159.1, + -159.11, + -159.12, + -159.14, + -158.01, + -158.02, + -158.03, + -158.04, + -158.05, + -158.06, + -158.07, + -158.08, + -158.09, + -158.1, + -158.11, + -158.12, + -157.01, + -157.02, + -157.03, + -157.04, + -157.05, + -157.06, + -157.07, + -157.08, + -157.09, + -157.1, + -157.11, + -157.12, + -156.01, + -156.02, + -156.03, + -156.04, + -156.05, + -156.06, + -156.07, + -156.08, + -156.09, + -156.1, + -156.11, + -156.12, + -156.14, + -155.01, + -155.02, + -155.03, + -155.04, + -155.05, + -155.06, + -155.07, + -155.08, + -155.09, + -155.1, + -155.11, + -155.12, + -154.01, + -154.02, + -154.03, + -154.04, + -154.05, + -154.06, + -154.07, + -154.08, + -154.09, + -154.1, + -154.11, + -154.12, + -153.01, + -153.02, + -153.03, + -153.04, + -153.05, + -153.06, + -153.13, + -153.07, + -153.08, + -153.09, + -153.1, + -153.11, + -153.12, + -152.01, + -152.02, + -152.03, + -152.04, + -152.05, + -152.06, + -152.07, + -152.08, + -152.09, + -152.1, + -152.11, + -152.12, + -151.01, + -151.02, + -151.03, + -151.04, + -151.05, + -151.06, + -151.07, + -151.08, + -151.09, + -151.1, + -151.11, + -151.12, + -151.14, + -150.01, + -150.02, + -150.03, + -150.04, + -150.05, + -150.06, + -150.07, + -150.08, + -150.09, + -150.1, + -150.11, + -150.12, + -149.01, + -149.02, + -149.03, + -149.04, + -149.05, + -149.06, + -149.07, + -149.08, + -149.09, + -149.1, + -149.11, + -149.12, + -148.01, + -148.02, + -148.03, + -148.04, + -148.05, + -148.06, + -148.07, + -148.08, + -148.09, + -148.1, + -148.11, + -148.12, + -148.14, + -147.01, + -147.02, + -147.03, + -147.04, + -147.05, + -147.06, + -147.07, + -147.08, + -147.09, + -147.1, + -147.11, + -147.12, + -146.01, + -146.02, + -146.03, + -146.04, + -146.05, + -146.06, + -146.07, + -146.08, + -146.09, + -146.1, + -146.11, + -146.12, + -145.01, + -145.02, + -145.03, + -145.04, + -145.05, + -145.06, + -145.07, + -145.08, + -145.09, + -145.1, + -145.11, + -145.12, + -145.14, + -144.01, + -144.02, + -144.03, + -144.04, + -144.05, + -144.06, + -144.07, + -144.08, + -144.09, + -144.1, + -144.11, + -144.12, + -143.01, + -143.02, + -143.03, + -143.04, + -143.05, + -143.06, + -143.07, + -143.08, + -143.09, + -143.1, + -143.11, + -143.12, + -143.14, + -142.01, + -142.02, + -142.03, + -142.04, + -142.05, + -142.06, + -142.07, + -142.08, + -142.09, + -142.1, + -142.11, + -142.12, + -141.01, + -141.02, + -141.03, + -141.04, + -141.05, + -141.06, + -141.07, + -141.08, + -141.09, + -141.1, + -141.11, + -141.12, + -140.01, + -140.02, + -140.03, + -140.04, + -140.05, + -140.06, + -140.07, + -140.08, + -140.09, + -140.1, + -140.11, + -140.12, + -140.14, + -139.01, + -139.02, + -139.03, + -139.04, + -139.05, + -139.06, + -139.07, + -139.08, + -139.09, + -139.1, + -139.11, + -139.12, + -138.01, + -138.02, + -138.03, + -138.04, + -138.05, + -138.06, + -138.07, + -138.08, + -138.09, + -138.1, + -138.11, + -138.12, + -137.01, + -137.02, + -137.03, + -137.04, + -137.05, + -137.06, + -137.07, + -137.08, + -137.09, + -137.1, + -137.11, + -137.12, + -137.14, + -136.01, + -136.02, + -136.03, + -136.04, + -136.05, + -136.06, + -136.07, + -136.08, + -136.09, + -136.1, + -136.11, + -136.12, + -135.01, + -135.02, + -135.03, + -135.04, + -135.05, + -135.06, + -135.07, + -135.08, + -135.09, + -135.1, + -135.11, + -135.12, + -134.01, + -134.02, + -134.03, + -134.04, + -134.05, + -134.06, + -134.07, + -134.08, + -134.09, + -134.1, + -134.11, + -134.12, + -134.14, + -133.01, + -133.02, + -133.03, + -133.04, + -133.05, + -133.06, + -133.07, + -133.08, + -133.09, + -133.1, + -133.11, + -133.12, + -132.01, + -132.02, + -132.03, + -132.04, + -132.05, + -132.06, + -132.07, + -132.08, + -132.09, + -132.1, + -132.11, + -132.12, + -132.14, + -131.01, + -131.02, + -131.03, + -131.04, + -131.05, + -131.06, + -131.07, + -131.08, + -131.09, + -131.1, + -131.11, + -131.12, + -130.01, + -130.02, + -130.03, + -130.04, + -130.05, + -130.06, + -130.07, + -130.08, + -130.09, + -130.1, + -130.11, + -130.12, + -129.01, + -129.02, + -129.03, + -129.04, + -129.05, + -129.06, + -129.07, + -129.08, + -129.09, + -129.1, + -129.11, + -129.12, + -129.14, + -128.01, + -128.02, + -128.03, + -128.04, + -128.05, + -128.06, + -128.07, + -128.08, + -128.09, + -128.1, + -128.11, + -128.12, + -127.01, + -127.02, + -127.03, + -127.04, + -127.05, + -127.06, + -127.07, + -127.08, + -127.09, + -127.1, + -127.11, + -127.12, + -126.01, + -126.02, + -126.03, + -126.04, + -126.05, + -126.06, + -126.07, + -126.08, + -126.09, + -126.1, + -126.11, + -126.12, + -126.14, + -125.01, + -125.02, + -125.03, + -125.04, + -125.05, + -125.06, + -125.07, + -125.08, + -125.09, + -125.1, + -125.11, + -125.12, + -124.01, + -124.02, + -124.03, + -124.04, + -124.05, + -124.06, + -124.07, + -124.08, + -124.09, + -124.1, + -124.11, + -124.12, + -124.14, + -123.01, + -123.02, + -123.03, + -123.04, + -123.05, + -123.06, + -123.07, + -123.08, + -123.09, + -123.1, + -123.11, + -123.12, + -122.01, + -122.02, + -122.03, + -122.04, + -122.05, + -122.06, + -122.07, + -122.08, + -122.09, + -122.1, + -122.11, + -122.12, + -121.01, + -121.02, + -121.03, + -121.04, + -121.05, + -121.06, + -121.07, + -121.08, + -121.09, + -121.1, + -121.11, + -121.12, + -121.14, + -120.01, + -120.02, + -120.03, + -120.04, + -120.05, + -120.06, + -120.07, + -120.08, + -120.09, + -120.1, + -120.11, + -120.12, + -119.01, + -119.02, + -119.03, + -119.04, + -119.05, + -119.06, + -119.07, + -119.08, + -119.09, + -119.1, + -119.11, + -119.12, + -118.01, + -118.02, + -118.03, + -118.04, + -118.05, + -118.06, + -118.07, + -118.08, + -118.09, + -118.1, + -118.11, + -118.12, + -118.14, + -117.01, + -117.02, + -117.03, + -117.04, + -117.05, + -117.06, + -117.07, + -117.08, + -117.09, + -117.1, + -117.11, + -117.12, + -116.01, + -116.02, + -116.03, + -116.04, + -116.05, + -116.06, + -116.07, + -116.08, + -116.09, + -116.1, + -116.11, + -116.12, + -115.01, + -115.02, + -115.03, + -115.04, + -115.05, + -115.06, + -115.07, + -115.08, + -115.09, + -115.1, + -115.11, + -115.12, + -115.14, + -114.01, + -114.02, + -114.03, + -114.04, + -114.05, + -114.06, + -114.07, + -114.08, + -114.09, + -114.1, + -114.11, + -114.12, + -113.01, + -113.02, + -113.03, + -113.04, + -113.05, + -113.06, + -113.07, + -113.08, + -113.09, + -113.1, + -113.11, + -113.12, + -113.14, + -112.01, + -112.02, + -112.03, + -112.04, + -112.05, + -112.06, + -112.07, + -112.08, + -112.09, + -112.1, + -112.11, + -112.12, + -111.01, + -111.02, + -111.03, + -111.04, + -111.05, + -111.06, + -111.07, + -111.08, + -111.09, + -111.1, + -111.11, + -111.12, + -110.01, + -110.02, + -110.03, + -110.04, + -110.05, + -110.06, + -110.07, + -110.08, + -110.09, + -110.1, + -110.11, + -110.12, + -110.14, + -109.01, + -109.02, + -109.03, + -109.04, + -109.05, + -109.06, + -109.07, + -109.08, + -109.09, + -109.1, + -109.11, + -109.12, + -108.01, + -108.02, + -108.03, + -108.04, + -108.05, + -108.06, + -108.07, + -108.08, + -108.09, + -108.1, + -108.11, + -108.12, + -107.01, + -107.02, + -107.03, + -107.04, + -107.05, + -107.06, + -107.07, + -107.08, + -107.09, + -107.1, + -107.11, + -107.12, + -107.14, + -106.01, + -106.02, + -106.03, + -106.04, + -106.05, + -106.06, + -106.07, + -106.08, + -106.09, + -106.1, + -106.11, + -106.12, + -105.01, + -105.02, + -105.03, + -105.04, + -105.05, + -105.06, + -105.07, + -105.08, + -105.09, + -105.1, + -105.11, + -105.12, + -105.14, + -104.01, + -104.02, + -104.03, + -104.04, + -104.05, + -104.06, + -104.07, + -104.08, + -104.09, + -104.1, + -104.11, + -104.12, + -103.01, + -103.02, + -103.03, + -103.04, + -103.05, + -103.06, + -103.07, + -103.08, + -103.09, + -103.1, + -103.11, + -103.12, + -102.01, + -102.02, + -102.03, + -102.04, + -102.05, + -102.06, + -102.07, + -102.08, + -102.09, + -102.1, + -102.11, + -102.12, + -102.14, + -101.01, + -101.02, + -101.03, + -101.04, + -101.05, + -101.06, + -101.07, + -101.08, + -101.09, + -101.1, + -101.11, + -101.12, + -100.01, + -100.02, + -100.03, + -100.04, + -100.05, + -100.06, + -100.07, + -100.08, + -100.09, + -100.1, + -100.11, + -100.12, + -99.01, + -99.02, + -99.03, + -99.04, + -99.05, + -99.06, + -99.07, + -99.08, + -99.09, + -99.1, + -99.11, + -99.12, + -99.14, + -98.01, + -98.02, + -98.03, + -98.04, + -98.05, + -98.06, + -98.07, + -98.08, + -98.09, + -98.1, + -98.11, + -98.12, + -97.01, + -97.02, + -97.03, + -97.04, + -97.05, + -97.06, + -97.07, + -97.08, + -97.09, + -97.1, + -97.11, + -97.12, + -96.01, + -96.02, + -96.03, + -96.04, + -96.05, + -96.06, + -96.13, + -96.07, + -96.08, + -96.09, + -96.1, + -96.11, + -96.12, + -95.01, + -95.02, + -95.03, + -95.04, + -95.05, + -95.06, + -95.07, + -95.08, + -95.09, + -95.1, + -95.11, + -95.12, + -94.01, + -94.02, + -94.03, + -94.04, + -94.05, + -94.06, + -94.07, + -94.08, + -94.09, + -94.1, + -94.11, + -94.12, + -94.14, + -93.01, + -93.02, + -93.03, + -93.04, + -93.05, + -93.06, + -93.07, + -93.08, + -93.09, + -93.1, + -93.11, + -93.12, + -92.01, + -92.02, + -92.03, + -92.04, + -92.05, + -92.06, + -92.07, + -92.08, + -92.09, + -92.1, + -92.11, + -92.12, + -91.01, + -91.02, + -91.03, + -91.04, + -91.05, + -91.06, + -91.07, + -91.08, + -91.09, + -91.1, + -91.11, + -91.12, + -91.14, + -90.01, + -90.02, + -90.03, + -90.04, + -90.05, + -90.06, + -90.07, + -90.08, + -90.09, + -90.1, + -90.11, + -90.12, + -89.01, + -89.02, + -89.03, + -89.04, + -89.05, + -89.06, + -89.07, + -89.08, + -89.09, + -89.1, + -89.11, + -89.12, + -88.01, + -88.02, + -88.03, + -88.04, + -88.05, + -88.06, + -88.07, + -88.08, + -88.09, + -88.1, + -88.11, + -88.12, + -88.14, + -87.01, + -87.02, + -87.03, + -87.04, + -87.05, + -87.06, + -87.07, + -87.08, + -87.09, + -87.1, + -87.11, + -87.12, + -86.01, + -86.02, + -86.03, + -86.04, + -86.05, + -86.06, + -86.07, + -86.08, + -86.09, + -86.1, + -86.11, + -86.12, + -86.14, + -85.01, + -85.02, + -85.03, + -85.04, + -85.05, + -85.06, + -85.07, + -85.08, + -85.09, + -85.1, + -85.11, + -85.12, + -84.01, + -84.02, + -84.03, + -84.04, + -84.05, + -84.06, + -84.07, + -84.08, + -84.09, + -84.1, + -84.11, + -84.12, + -83.01, + -83.02, + -83.03, + -83.04, + -83.05, + -83.06, + -83.07, + -83.08, + -83.09, + -83.1, + -83.11, + -83.12, + -83.14, + -82.01, + -82.02, + -82.03, + -82.04, + -82.05, + -82.06, + -82.07, + -82.08, + -82.09, + -82.1, + -82.11, + -82.12, + -81.01, + -81.02, + -81.03, + -81.04, + -81.05, + -81.06, + -81.07, + -81.08, + -81.09, + -81.1, + -81.11, + -81.12, + -80.01, + -80.02, + -80.03, + -80.04, + -80.05, + -80.06, + -80.07, + -80.08, + -80.09, + -80.1, + -80.11, + -80.12, + -80.14, + -79.01, + -79.02, + -79.03, + -79.04, + -79.05, + -79.06, + -79.07, + -79.08, + -79.09, + -79.1, + -79.11, + -79.12, + -78.01, + -78.02, + -78.03, + -78.04, + -78.05, + -78.06, + -78.07, + -78.08, + -78.09, + -78.1, + -78.11, + -78.12, + -77.01, + -77.02, + -77.03, + -77.04, + -77.05, + -77.06, + -77.13, + -77.07, + -77.08, + -77.09, + -77.1, + -77.11, + -77.12, + -76.01, + -76.02, + -76.03, + -76.04, + -76.05, + -76.06, + -76.07, + -76.08, + -76.09, + -76.1, + -76.11, + -76.12, + -75.01, + -75.02, + -75.03, + -75.04, + -75.05, + -75.06, + -75.07, + -75.08, + -75.09, + -75.1, + -75.11, + -75.12, + -75.14, + -74.01, + -74.02, + -74.03, + -74.04, + -74.05, + -74.06, + -74.07, + -74.08, + -74.09, + -74.1, + -74.11, + -74.12, + -73.01, + -73.02, + -73.03, + -73.04, + -73.05, + -73.06, + -73.07, + -73.08, + -73.09, + -73.1, + -73.11, + -73.12, + -73.14, + -72.01, + -72.02, + -72.03, + -72.04, + -72.05, + -72.06, + -72.07, + -72.08, + -72.09, + -72.1, + -72.11, + -72.12, + -71.01, + -71.02, + -71.03, + -71.04, + -71.05, + -71.06, + -71.07, + -71.08, + -71.09, + -71.1, + -71.11, + -71.12, + -70.01, + -70.02, + -70.03, + -70.04, + -70.05, + -70.06, + -70.07, + -70.08, + -70.09, + -70.1, + -70.11, + -70.12, + -69.01, + -69.02, + -69.03, + -69.04, + -69.05, + -69.06, + -69.07, + -69.08, + -69.09, + -69.1, + -69.11, + -69.12, + -69.14, + -68.01, + -68.02, + -68.03, + -68.04, + -68.05, + -68.06, + -68.07, + -68.08, + -68.09, + -68.1, + -68.11, + -68.12, + -67.01, + -67.02, + -67.03, + -67.04, + -67.05, + -67.06, + -67.07, + -67.08, + -67.09, + -67.1, + -67.11, + -67.12, + -67.14, + -66.01, + -66.02, + -66.03, + -66.04, + -66.05, + -66.06, + -66.07, + -66.08, + -66.09, + -66.1, + -66.11, + -66.12, + -65.01, + -65.02, + -65.03, + -65.04, + -65.05, + -65.06, + -65.07, + -65.08, + -65.09, + -65.1, + -65.11, + -65.12, + -64.01, + -64.02, + -64.03, + -64.04, + -64.05, + -64.06, + -64.07, + -64.08, + -64.09, + -64.1, + -64.11, + -64.12, + -64.14, + -63.01, + -63.02, + -63.03, + -63.04, + -63.05, + -63.06, + -63.07, + -63.08, + -63.09, + -63.1, + -63.11, + -63.12, + -62.01, + -62.02, + -62.03, + -62.04, + -62.05, + -62.06, + -62.07, + -62.08, + -62.09, + -62.1, + -62.11, + -62.12, + -61.01, + -61.02, + -61.03, + -61.04, + -61.05, + -61.06, + -61.07, + -61.08, + -61.09, + -61.1, + -61.11, + -61.12, + -61.14, + -60.01, + -60.02, + -60.03, + -60.04, + -60.05, + -60.06, + -60.07, + -60.08, + -60.09, + -60.1, + -60.11, + -60.12, + -59.01, + -59.02, + -59.03, + -59.04, + -59.05, + -59.06, + -59.07, + -59.08, + -59.09, + -59.1, + -59.11, + -59.12, + -58.01, + -58.02, + -58.03, + -58.04, + -58.05, + -58.06, + -58.13, + -58.07, + -58.08, + -58.09, + -58.1, + -58.11, + -58.12, + -57.01, + -57.02, + -57.03, + -57.04, + -57.05, + -57.06, + -57.07, + -57.08, + -57.09, + -57.1, + -57.11, + -57.12, + -56.01, + -56.02, + -56.03, + -56.04, + -56.05, + -56.06, + -56.07, + -56.08, + -56.09, + -56.1, + -56.11, + -56.12, + -56.14, + -55.01, + -55.02, + -55.03, + -55.04, + -55.05, + -55.06, + -55.07, + -55.08, + -55.09, + -55.1, + -55.11, + -55.12, + -54.01, + -54.02, + -54.03, + -54.04, + -54.05, + -54.06, + -54.07, + -54.08, + -54.09, + -54.1, + -54.11, + -54.12, + -53.01, + -53.02, + -53.03, + -53.04, + -53.05, + -53.06, + -53.07, + -53.08, + -53.09, + -53.1, + -53.11, + -53.12, + -53.14, + -52.01, + -52.02, + -52.03, + -52.04, + -52.05, + -52.06, + -52.07, + -52.08, + -52.09, + -52.1, + -52.11, + -52.12, + -51.01, + -51.02, + -51.03, + -51.04, + -51.05, + -51.06, + -51.07, + -51.08, + -51.09, + -51.1, + -51.11, + -51.12, + -50.01, + -50.02, + -50.03, + -50.04, + -50.05, + -50.06, + -50.07, + -50.08, + -50.09, + -50.1, + -50.11, + -50.12, + -50.14, + -49.01, + -49.02, + -49.03, + -49.04, + -49.05, + -49.06, + -49.07, + -49.08, + -49.09, + -49.1, + -49.11, + -49.12, + -48.01, + -48.02, + -48.03, + -48.04, + -48.05, + -48.06, + -48.07, + -48.08, + -48.09, + -48.1, + -48.11, + -48.12, + -48.14, + -47.01, + -47.02, + -47.03, + -47.04, + -47.05, + -47.06, + -47.07, + -47.08, + -47.09, + -47.1, + -47.11, + -47.12, + -46.01, + -46.02, + -46.03, + -46.04, + -46.05, + -46.06, + -46.07, + -46.08, + -46.09, + -46.1, + -46.11, + -46.12, + -45.01, + -45.02, + -45.03, + -45.04, + -45.05, + -45.06, + -45.07, + -45.08, + -45.09, + -45.1, + -45.11, + -45.12, + -45.14, + -44.01, + -44.02, + -44.03, + -44.04, + -44.05, + -44.06, + -44.07, + -44.08, + -44.09, + -44.1, + -44.11, + -44.12, + -43.01, + -43.02, + -43.03, + -43.04, + -43.05, + -43.06, + -43.07, + -43.08, + -43.09, + -43.1, + -43.11, + -43.12, + -42.01, + -42.02, + -42.03, + -42.04, + -42.05, + -42.06, + -42.07, + -42.08, + -42.09, + -42.1, + -42.11, + -42.12, + -42.14, + -41.01, + -41.02, + -41.03, + -41.04, + -41.05, + -41.06, + -41.07, + -41.08, + -41.09, + -41.1, + -41.11, + -41.12, + -40.01, + -40.02, + -40.03, + -40.04, + -40.05, + -40.06, + -40.07, + -40.08, + -40.09, + -40.1, + -40.11, + -40.12, + -39.01, + -39.02, + -39.03, + -39.04, + -39.05, + -39.06, + -39.13, + -39.07, + -39.08, + -39.09, + -39.1, + -39.11, + -39.12, + -38.01, + -38.02, + -38.03, + -38.04, + -38.05, + -38.06, + -38.07, + -38.08, + -38.09, + -38.1, + -38.11, + -38.12, + -37.01, + -37.02, + -37.03, + -37.04, + -37.05, + -37.06, + -37.07, + -37.08, + -37.09, + -37.1, + -37.11, + -37.12, + -37.14, + -36.01, + -36.02, + -36.03, + -36.04, + -36.05, + -36.06, + -36.07, + -36.08, + -36.09, + -36.1, + -36.11, + -36.12, + -35.01, + -35.02, + -35.03, + -35.04, + -35.05, + -35.06, + -35.07, + -35.08, + -35.09, + -35.1, + -35.11, + -35.12, + -34.01, + -34.02, + -34.03, + -34.04, + -34.05, + -34.06, + -34.07, + -34.08, + -34.09, + -34.1, + -34.11, + -34.12, + -34.14, + -33.01, + -33.02, + -33.03, + -33.04, + -33.05, + -33.06, + -33.07, + -33.08, + -33.09, + -33.1, + -33.11, + -33.12, + -32.01, + -32.02, + -32.03, + -32.04, + -32.05, + -32.06, + -32.07, + -32.08, + -32.09, + -32.1, + -32.11, + -32.12, + -31.01, + -31.02, + -31.03, + -31.04, + -31.05, + -31.06, + -31.07, + -31.08, + -31.09, + -31.1, + -31.11, + -31.12, + -31.14, + -30.01, + -30.02, + -30.03, + -30.04, + -30.05, + -30.06, + -30.07, + -30.08, + -30.09, + -30.1, + -30.11, + -30.12, + -29.01, + -29.02, + -29.03, + -29.04, + -29.05, + -29.06, + -29.07, + -29.08, + -29.09, + -29.1, + -29.11, + -29.12, + -29.14, + -28.01, + -28.02, + -28.03, + -28.04, + -28.05, + -28.06, + -28.07, + -28.08, + -28.09, + -28.1, + -28.11, + -28.12, + -27.01, + -27.02, + -27.03, + -27.04, + -27.05, + -27.06, + -27.07, + -27.08, + -27.09, + -27.1, + -27.11, + -27.12, + -26.01, + -26.02, + -26.03, + -26.04, + -26.05, + -26.06, + -26.07, + -26.08, + -26.09, + -26.1, + -26.11, + -26.12, + -26.14, + -25.01, + -25.02, + -25.03, + -25.04, + -25.05, + -25.06, + -25.07, + -25.08, + -25.09, + -25.1, + -25.11, + -25.12, + -24.01, + -24.02, + -24.03, + -24.04, + -24.05, + -24.06, + -24.07, + -24.08, + -24.09, + -24.1, + -24.11, + -24.12, + -23.01, + -23.02, + -23.03, + -23.04, + -23.05, + -23.06, + -23.07, + -23.08, + -23.09, + -23.1, + -23.11, + -23.12, + -23.14, + -22.01, + -22.02, + -22.03, + -22.04, + -22.05, + -22.06, + -22.07, + -22.08, + -22.09, + -22.1, + -22.11, + -22.12, + -21.01, + -21.02, + -21.03, + -21.04, + -21.05, + -21.06, + -21.07, + -21.08, + -21.09, + -21.1, + -21.11, + -21.12, + -20.01, + -20.02, + -20.03, + -20.04, + -20.05, + -20.06, + -20.13, + -20.07, + -20.08, + -20.09, + -20.1, + -20.11, + -20.12, + -19.01, + -19.02, + -19.03, + -19.04, + -19.05, + -19.06, + -19.07, + -19.08, + -19.09, + -19.1, + -19.11, + -19.12, + -18.01, + -18.02, + -18.03, + -18.04, + -18.05, + -18.06, + -18.07, + -18.08, + -18.09, + -18.1, + -18.11, + -18.12, + -18.14, + -17.01, + -17.02, + -17.03, + -17.04, + -17.05, + -17.06, + -17.07, + -17.08, + -17.09, + -17.1, + -17.11, + -17.12, + -16.01, + -16.02, + -16.03, + -16.04, + -16.05, + -16.06, + -16.07, + -16.08, + -16.09, + -16.1, + -16.11, + -16.12, + -15.01, + -15.02, + -15.03, + -15.04, + -15.05, + -15.06, + -15.07, + -15.08, + -15.09, + -15.1, + -15.11, + -15.12, + -15.14, + -14.01, + -14.02, + -14.03, + -14.04, + -14.05, + -14.06, + -14.07, + -14.08, + -14.09, + -14.1, + -14.11, + -14.12, + -13.01, + -13.02, + -13.03, + -13.04, + -13.05, + -13.06, + -13.07, + -13.08, + -13.09, + -13.1, + -13.11, + -13.12, + -12.01, + -12.02, + -12.03, + -12.04, + -12.05, + -12.06, + -12.07, + -12.08, + -12.09, + -12.1, + -12.11, + -12.12, + -12.14, + -11.01, + -11.02, + -11.03, + -11.04, + -11.05, + -11.06, + -11.07, + -11.08, + -11.09, + -11.1, + -11.11, + -11.12, + -10.01, + -10.02, + -10.03, + -10.04, + -10.05, + -10.06, + -10.07, + -10.08, + -10.09, + -10.1, + -10.11, + -10.12, + -10.14, + -9.01, + -9.02, + -9.03, + -9.04, + -9.05, + -9.06, + -9.07, + -9.08, + -9.09, + -9.1, + -9.11, + -9.12, + -8.01, + -8.02, + -8.03, + -8.04, + -8.05, + -8.06, + -8.07, + -8.08, + -8.09, + -8.1, + -8.11, + -8.12, + -7.01, + -7.02, + -7.03, + -7.04, + -7.05, + -7.06, + -7.07, + -7.08, + -7.09, + -7.1, + -7.11, + -7.12, + -7.14, + -6.01, + -6.02, + -6.03, + -6.04, + -6.05, + -6.06, + -6.07, + -6.08, + -6.09, + -6.1, + -6.11, + -6.12, + -5.01, + -5.02, + -5.03, + -5.04, + -5.05, + -5.06, + -5.07, + -5.08, + -5.09, + -5.1, + -5.11, + -5.12, + -4.01, + -4.02, + -4.03, + -4.04, + -4.05, + -4.06, + -4.07, + -4.08, + -4.09, + -4.1, + -4.11, + -4.12, + -4.14, + -3.01, + -3.02, + -3.03, + -3.04, + -3.05, + -3.06, + -3.07, + -3.08, + -3.09, + -3.1, + -3.11, + -3.12, + -2.01, + -2.02, + -2.03, + -2.04, + -2.05, + -2.06, + -2.07, + -2.08, + -2.09, + -2.1, + -2.11, + -2.12, + -1.01, + -1.02, + -1.03, + -1.04, + -1.05, + -1.06, + -1.13, + -1.07, + -1.08, + -1.09, + -1.1, + -1.11, + -1.12, + 0.01, + 0.02, + 0.03, + 0.04, + 0.05, + 0.06, + 0.07, + 0.08, + 0.09, + 0.1, + 0.11, + 0.12, + 1.01, + 1.02, + 1.03, + 1.04, + 1.05, + 1.06, + 1.07, + 1.08, + 1.09, + 1.1, + 1.11, + 1.12, + 1.14, + 2.01, + 2.02, + 2.03, + 2.04, + 2.05, + 2.06, + 2.07, + 2.08, + 2.09, + 2.1, + 2.11, + 2.12, + 3.01, + 3.02, + 3.03, + 3.04, + 3.05, + 3.06, + 3.07, + 3.08, + 3.09, + 3.1, + 3.11, + 3.12, + 4.01, + 4.02, + 4.03, + 4.04, + 4.05, + 4.06, + 4.07, + 4.08, + 4.09, + 4.1, + 4.11, + 4.12, + 4.14, + 5.01, + 5.02, + 5.03, + 5.04, + 5.05, + 5.06, + 5.07, + 5.08, + 5.09, + 5.1, + 5.11, + 5.12, + 6.01, + 6.02, + 6.03, + 6.04, + 6.05, + 6.06, + 6.07, + 6.08, + 6.09, + 6.1, + 6.11, + 6.12, + 7.01, + 7.02, + 7.03, + 7.04, + 7.05, + 7.06, + 7.07, + 7.08, + 7.09, + 7.1, + 7.11, + 7.12, + 7.14, + 8.01, + 8.02, + 8.03, + 8.04, + 8.05, + 8.06, + 8.07, + 8.08, + 8.09, + 8.1, + 8.11, + 8.12, + 9.01, + 9.02, + 9.03, + 9.04, + 9.05, + 9.06, + 9.07, + 9.08, + 9.09, + 9.1, + 9.11, + 9.12, + 9.14, + 10.01, + 10.02, + 10.03, + 10.04, + 10.05, + 10.06, + 10.07, + 10.08, + 10.09, + 10.1, + 10.11, + 10.12, + 11.01, + 11.02, + 11.03, + 11.04, + 11.05, + 11.06, + 11.07, + 11.08, + 11.09, + 11.1, + 11.11, + 11.12, + 12.01, + 12.02, + 12.03, + 12.04, + 12.05, + 12.06, + 12.07, + 12.08, + 12.09, + 12.1, + 12.11, + 12.12, + 12.14, + 13.01, + 13.02, + 13.03, + 13.04, + 13.05, + 13.06, + 13.07, + 13.08, + 13.09, + 13.1, + 13.11, + 13.12, + 14.01, + 14.02, + 14.03, + 14.04, + 14.05, + 14.06, + 14.07, + 14.08, + 14.09, + 14.1, + 14.11, + 14.12, + 15.01, + 15.02, + 15.03, + 15.04, + 15.05, + 15.06, + 15.07, + 15.08, + 15.09, + 15.1, + 15.11, + 15.12, + 15.14, + 16.01, + 16.02, + 16.03, + 16.04, + 16.05, + 16.06, + 16.07, + 16.08, + 16.09, + 16.1, + 16.11, + 16.12, + 17.01, + 17.02, + 17.03, + 17.04, + 17.05, + 17.06, + 17.07, + 17.08, + 17.09, + 17.1, + 17.11, + 17.12, + 18.01, + 18.02, + 18.03, + 18.04, + 18.05, + 18.06, + 18.13, + 18.07, + 18.08, + 18.09, + 18.1, + 18.11, + 18.12, + 19.01, + 19.02, + 19.03, + 19.04, + 19.05, + 19.06, + 19.07, + 19.08, + 19.09, + 19.1, + 19.11, + 19.12, + 20.01, + 20.02, + 20.03, + 20.04, + 20.05, + 20.06, + 20.07, + 20.08, + 20.09, + 20.1, + 20.11, + 20.12, + 20.14, + 21.01, + 21.02, + 21.03, + 21.04, + 21.05, + 21.06, + 21.07, + 21.08, + 21.09, + 21.1, + 21.11, + 21.12, + 22.01, + 22.02, + 22.03, + 22.04, + 22.05, + 22.06, + 22.07, + 22.08, + 22.09, + 22.1, + 22.11, + 22.12, + 23.01, + 23.02, + 23.03, + 23.04, + 23.05, + 23.06, + 23.07, + 23.08, + 23.09, + 23.1, + 23.11, + 23.12, + 23.14, + 24.01, + 24.02, + 24.03, + 24.04, + 24.05, + 24.06, + 24.07, + 24.08, + 24.09, + 24.1, + 24.11, + 24.12, + 25.01, + 25.02, + 25.03, + 25.04, + 25.05, + 25.06, + 25.07, + 25.08, + 25.09, + 25.1, + 25.11, + 25.12, + 26.01, + 26.02, + 26.03, + 26.04, + 26.05, + 26.06, + 26.07, + 26.08, + 26.09, + 26.1, + 26.11, + 26.12, + 26.14, + 27.01, + 27.02, + 27.03, + 27.04, + 27.05, + 27.06, + 27.07, + 27.08, + 27.09, + 27.1, + 27.11, + 27.12, + 28.01, + 28.02, + 28.03, + 28.04, + 28.05, + 28.06, + 28.07, + 28.08, + 28.09, + 28.1, + 28.11, + 28.12, + 28.14, + 29.01, + 29.02, + 29.03, + 29.04, + 29.05, + 29.06, + 29.07, + 29.08, + 29.09, + 29.1, + 29.11, + 29.12, + 30.01, + 30.02, + 30.03, + 30.04, + 30.05, + 30.06, + 30.07, + 30.08, + 30.09, + 30.1, + 30.11, + 30.12, + 31.01, + 31.02, + 31.03, + 31.04, + 31.05, + 31.06, + 31.07, + 31.08, + 31.09, + 31.1, + 31.11, + 31.12, + 31.14, + 32.01, + 32.02, + 32.03, + 32.04, + 32.05, + 32.06, + 32.07, + 32.08, + 32.09, + 32.1, + 32.11, + 32.12, + 33.01, + 33.02, + 33.03, + 33.04, + 33.05, + 33.06, + 33.07, + 33.08, + 33.09, + 33.1, + 33.11, + 33.12, + 34.01, + 34.02, + 34.03, + 34.04, + 34.05, + 34.06, + 34.07, + 34.08, + 34.09, + 34.1, + 34.11, + 34.12, + 34.14, + 35.01, + 35.02, + 35.03, + 35.04, + 35.05, + 35.06, + 35.07, + 35.08, + 35.09, + 35.1, + 35.11, + 35.12, + 36.01, + 36.02, + 36.03, + 36.04, + 36.05, + 36.06, + 36.07, + 36.08, + 36.09, + 36.1, + 36.11, + 36.12, + 37.01, + 37.02, + 37.03, + 37.04, + 37.05, + 37.06, + 37.13, + 37.07, + 37.08, + 37.09, + 37.1, + 37.11, + 37.12, + 38.01, + 38.02, + 38.03, + 38.04, + 38.05, + 38.06, + 38.07, + 38.08, + 38.09, + 38.1, + 38.11, + 38.12, + 39.01, + 39.02, + 39.03, + 39.04, + 39.05, + 39.06, + 39.07, + 39.08, + 39.09, + 39.1, + 39.11, + 39.12, + 39.14, + 40.01, + 40.02, + 40.03, + 40.04, + 40.05, + 40.06, + 40.07, + 40.08, + 40.09, + 40.1, + 40.11, + 40.12, + 41.01, + 41.02, + 41.03, + 41.04, + 41.05, + 41.06, + 41.07, + 41.08, + 41.09, + 41.1, + 41.11, + 41.12, + 42.01, + 42.02, + 42.03, + 42.04, + 42.05, + 42.06, + 42.07, + 42.08, + 42.09, + 42.1, + 42.11, + 42.12, + 42.14, + 43.01, + 43.02, + 43.03, + 43.04, + 43.05, + 43.06, + 43.07, + 43.08, + 43.09, + 43.1, + 43.11, + 43.12, + 44.01, + 44.02, + 44.03, + 44.04, + 44.05, + 44.06, + 44.07, + 44.08, + 44.09, + 44.1, + 44.11, + 44.12, + 45.01, + 45.02, + 45.03, + 45.04, + 45.05, + 45.06, + 45.07, + 45.08, + 45.09, + 45.1, + 45.11, + 45.12, + 45.14, + 46.01, + 46.02, + 46.03, + 46.04, + 46.05, + 46.06, + 46.07, + 46.08, + 46.09, + 46.1, + 46.11, + 46.12, + 47.01, + 47.02, + 47.03, + 47.04, + 47.05, + 47.06, + 47.07, + 47.08, + 47.09, + 47.1, + 47.11, + 47.12, + 47.14, + 48.01, + 48.02, + 48.03, + 48.04, + 48.05, + 48.06, + 48.07, + 48.08, + 48.09, + 48.1, + 48.11, + 48.12, + 49.01, + 49.02, + 49.03, + 49.04, + 49.05, + 49.06, + 49.07, + 49.08, + 49.09, + 49.1, + 49.11, + 49.12, + 50.01, + 50.02, + 50.03, + 50.04, + 50.05, + 50.06, + 50.07, + 50.08, + 50.09, + 50.1, + 50.11, + 50.12, + 50.14, + 51.01, + 51.02, + 51.03, + 51.04, + 51.05, + 51.06, + 51.07, + 51.08, + 51.09, + 51.1, + 51.11, + 51.12, + 52.01, + 52.02, + 52.03, + 52.04, + 52.05, + 52.06, + 52.07, + 52.08, + 52.09, + 52.1, + 52.11, + 52.12, + 53.01, + 53.02, + 53.03, + 53.04, + 53.05, + 53.06, + 53.07, + 53.08, + 53.09, + 53.1, + 53.11, + 53.12, + 53.14, + 54.01, + 54.02, + 54.03, + 54.04, + 54.05, + 54.06, + 54.07, + 54.08, + 54.09, + 54.1, + 54.11, + 54.12, + 55.01, + 55.02, + 55.03, + 55.04, + 55.05, + 55.06, + 55.07, + 55.08, + 55.09, + 55.1, + 55.11, + 55.12, + 56.01, + 56.02, + 56.03, + 56.04, + 56.05, + 56.06, + 56.13, + 56.07, + 56.08, + 56.09, + 56.1, + 56.11, + 56.12, + 57.01, + 57.02, + 57.03, + 57.04, + 57.05, + 57.06, + 57.07, + 57.08, + 57.09, + 57.1, + 57.11, + 57.12, + 58.01, + 58.02, + 58.03, + 58.04, + 58.05, + 58.06, + 58.07, + 58.08, + 58.09, + 58.1, + 58.11, + 58.12, + 58.14, + 59.01, + 59.02, + 59.03, + 59.04, + 59.05, + 59.06, + 59.07, + 59.08, + 59.09, + 59.1, + 59.11, + 59.12, + 60.01, + 60.02, + 60.03, + 60.04, + 60.05, + 60.06, + 60.07, + 60.08, + 60.09, + 60.1, + 60.11, + 60.12, + 61.01, + 61.02, + 61.03, + 61.04, + 61.05, + 61.06, + 61.07, + 61.08, + 61.09, + 61.1, + 61.11, + 61.12, + 61.14, + 62.01, + 62.02, + 62.03, + 62.04, + 62.05, + 62.06, + 62.07, + 62.08, + 62.09, + 62.1, + 62.11, + 62.12, + 63.01, + 63.02, + 63.03, + 63.04, + 63.05, + 63.06, + 63.07, + 63.08, + 63.09, + 63.1, + 63.11, + 63.12, + 64.01, + 64.02, + 64.03, + 64.04, + 64.05, + 64.06, + 64.07, + 64.08, + 64.09, + 64.1, + 64.11, + 64.12, + 64.14, + 65.01, + 65.02, + 65.03, + 65.04, + 65.05, + 65.06, + 65.07, + 65.08, + 65.09, + 65.1, + 65.11, + 65.12, + 66.01, + 66.02, + 66.03, + 66.04, + 66.05, + 66.06, + 66.07, + 66.08, + 66.09, + 66.1, + 66.11, + 66.12, + 66.14, + 67.01, + 67.02, + 67.03, + 67.04, + 67.05, + 67.06, + 67.07, + 67.08, + 67.09, + 67.1, + 67.11, + 67.12, + 68.01, + 68.02, + 68.03, + 68.04, + 68.05, + 68.06, + 68.07, + 68.08, + 68.09, + 68.1, + 68.11, + 68.12, + 69.01, + 69.02, + 69.03, + 69.04, + 69.05, + 69.06, + 69.07, + 69.08, + 69.09, + 69.1, + 69.11, + 69.12, + 69.14, + 70.01, + 70.02, + 70.03, + 70.04, + 70.05, + 70.06, + 70.07, + 70.08, + 70.09, + 70.1, + 70.11, + 70.12, + 71.01, + 71.02, + 71.03, + 71.04, + 71.05, + 71.06, + 71.07, + 71.08, + 71.09, + 71.1, + 71.11, + 71.12, + 72.01, + 72.02, + 72.03, + 72.04, + 72.05, + 72.06, + 72.07, + 72.08, + 72.09, + 72.1, + 72.11, + 72.12, + 72.14, + 73.01, + 73.02, + 73.03, + 73.04, + 73.05, + 73.06, + 73.07, + 73.08, + 73.09, + 73.1, + 73.11, + 73.12, + 74.01, + 74.02, + 74.03, + 74.04, + 74.05, + 74.06, + 74.07, + 74.08, + 74.09, + 74.1, + 74.11, + 74.12, + 75.01, + 75.02, + 75.03, + 75.04, + 75.05, + 75.06, + 75.13, + 75.07, + 75.08, + 75.09, + 75.1, + 75.11, + 75.12, + 76.01, + 76.02, + 76.03, + 76.04, + 76.05, + 76.06, + 76.07, + 76.08, + 76.09, + 76.1, + 76.11, + 76.12, + 77.01, + 77.02, + 77.03, + 77.04, + 77.05, + 77.06, + 77.07, + 77.08, + 77.09, + 77.1, + 77.11, + 77.12, + 77.14, + 78.01, + 78.02, + 78.03, + 78.04, + 78.05, + 78.06, + 78.07, + 78.08, + 78.09, + 78.1, + 78.11, + 78.12, + 79.01, + 79.02, + 79.03, + 79.04, + 79.05, + 79.06, + 79.07, + 79.08, + 79.09, + 79.1, + 79.11, + 79.12, + 80.01, + 80.02, + 80.03, + 80.04, + 80.05, + 80.06, + 80.07, + 80.08, + 80.09, + 80.1, + 80.11, + 80.12, + 80.14, + 81.01, + 81.02, + 81.03, + 81.04, + 81.05, + 81.06, + 81.07, + 81.08, + 81.09, + 81.1, + 81.11, + 81.12, + 82.01, + 82.02, + 82.03, + 82.04, + 82.05, + 82.06, + 82.07, + 82.08, + 82.09, + 82.1, + 82.11, + 82.12, + 83.01, + 83.02, + 83.03, + 83.04, + 83.05, + 83.06, + 83.07, + 83.08, + 83.09, + 83.1, + 83.11, + 83.12, + 83.14, + 84.01, + 84.02, + 84.03, + 84.04, + 84.05, + 84.06, + 84.07, + 84.08, + 84.09, + 84.1, + 84.11, + 84.12, + 85.01, + 85.02, + 85.03, + 85.04, + 85.05, + 85.06, + 85.07, + 85.08, + 85.09, + 85.1, + 85.11, + 85.12, + 85.14, + 86.01, + 86.02, + 86.03, + 86.04, + 86.05, + 86.06, + 86.07, + 86.08, + 86.09, + 86.1, + 86.11, + 86.12, + 87.01, + 87.02, + 87.03, + 87.04, + 87.05, + 87.06, + 87.07, + 87.08, + 87.09, + 87.1, + 87.11, + 87.12, + 88.01, + 88.02, + 88.03, + 88.04, + 88.05, + 88.06, + 88.07, + 88.08, + 88.09, + 88.1, + 88.11, + 88.12, + 88.14, + 89.01, + 89.02, + 89.03, + 89.04, + 89.05, + 89.06, + 89.07, + 89.08, + 89.09, + 89.1, + 89.11, + 89.12, + 90.01, + 90.02, + 90.03, + 90.04, + 90.05, + 90.06, + 90.07, + 90.08, + 90.09, + 90.1, + 90.11, + 90.12, + 91.01, + 91.02, + 91.03, + 91.04, + 91.05, + 91.06, + 91.07, + 91.08, + 91.09, + 91.1, + 91.11, + 91.12, + 91.14, + 92.01, + 92.02, + 92.03, + 92.04, + 92.05, + 92.06, + 92.07, + 92.08, + 92.09, + 92.1, + 92.11, + 92.12, + 93.01, + 93.02, + 93.03, + 93.04, + 93.05, + 93.06, + 93.07, + 93.08, + 93.09, + 93.1, + 93.11, + 93.12, + 94.01, + 94.02, + 94.03, + 94.04, + 94.05, + 94.06, + 94.13, + 94.07, + 94.08, + 94.09, + 94.1, + 94.11, + 94.12, + 95.01, + 95.02, + 95.03, + 95.04, + 95.05, + 95.06, + 95.07, + 95.08, + 95.09, + 95.1, + 95.11, + 95.12, + 96.01, + 96.02, + 96.03, + 96.04, + 96.05, + 96.06, + 96.07, + 96.08, + 96.09, + 96.1, + 96.11, + 96.12, + 96.14, + 97.01, + 97.02, + 97.03, + 97.04, + 97.05, + 97.06, + 97.07, + 97.08, + 97.09, + 97.1, + 97.11, + 97.12, + 98.01, + 98.02, + 98.03, + 98.04, + 98.05, + 98.06, + 98.07, + 98.08, + 98.09, + 98.1, + 98.11, + 98.12, + 99.01, + 99.02, + 99.03, + 99.04, + 99.05, + 99.06, + 99.07, + 99.08, + 99.09, + 99.1, + 99.11, + 99.12, + 99.14, + 100.01, + 100.02, + 100.03, + 100.04, + 100.05, + 100.06, + 100.07, + 100.08, + 100.09, + 100.1, + 100.11, + 100.12, + 101.01, + 101.02, + 101.03, + 101.04, + 101.05, + 101.06, + 101.07, + 101.08, + 101.09, + 101.1, + 101.11, + 101.12, + 102.01, + 102.02, + 102.03, + 102.04, + 102.05, + 102.06, + 102.07, + 102.08, + 102.09, + 102.1, + 102.11, + 102.12, + 102.14, + 103.01, + 103.02, + 103.03, + 103.04, + 103.05, + 103.06, + 103.07, + 103.08, + 103.09, + 103.1, + 103.11, + 103.12, + 104.01, + 104.02, + 104.03, + 104.04, + 104.05, + 104.06, + 104.07, + 104.08, + 104.09, + 104.1, + 104.11, + 104.12, + 104.14, + 105.01, + 105.02, + 105.03, + 105.04, + 105.05, + 105.06, + 105.07, + 105.08, + 105.09, + 105.1, + 105.11, + 105.12, + 106.01, + 106.02, + 106.03, + 106.04, + 106.05, + 106.06, + 106.07, + 106.08, + 106.09, + 106.1, + 106.11, + 106.12, + 107.01, + 107.02, + 107.03, + 107.04, + 107.05, + 107.06, + 107.07, + 107.08, + 107.09, + 107.1, + 107.11, + 107.12, + 107.14, + 108.01, + 108.02, + 108.03, + 108.04, + 108.05, + 108.06, + 108.07, + 108.08, + 108.09, + 108.1, + 108.11, + 108.12, + 109.01, + 109.02, + 109.03, + 109.04, + 109.05, + 109.06, + 109.07, + 109.08, + 109.09, + 109.1, + 109.11, + 109.12, + 110.01, + 110.02, + 110.03, + 110.04, + 110.05, + 110.06, + 110.07, + 110.08, + 110.09, + 110.1, + 110.11, + 110.12, + 110.14, + 111.01, + 111.02, + 111.03, + 111.04, + 111.05, + 111.06, + 111.07, + 111.08, + 111.09, + 111.1, + 111.11, + 111.12, + 112.01, + 112.02, + 112.03, + 112.04, + 112.05, + 112.06, + 112.07, + 112.08, + 112.09, + 112.1, + 112.11, + 112.12, + 113.01, + 113.02, + 113.03, + 113.04, + 113.05, + 113.06, + 113.13, + 113.07, + 113.08, + 113.09, + 113.1, + 113.11, + 113.12, + 114.01, + 114.02, + 114.03, + 114.04, + 114.05, + 114.06, + 114.07, + 114.08, + 114.09, + 114.1, + 114.11, + 114.12, + 115.01, + 115.02, + 115.03, + 115.04, + 115.05, + 115.06, + 115.07, + 115.08, + 115.09, + 115.1, + 115.11, + 115.12, + 115.14, + 116.01, + 116.02, + 116.03, + 116.04, + 116.05, + 116.06, + 116.07, + 116.08, + 116.09, + 116.1, + 116.11, + 116.12, + 117.01, + 117.02, + 117.03, + 117.04, + 117.05, + 117.06, + 117.07, + 117.08, + 117.09, + 117.1, + 117.11, + 117.12, + 118.01, + 118.02, + 118.03, + 118.04, + 118.05, + 118.06, + 118.07, + 118.08, + 118.09, + 118.1, + 118.11, + 118.12, + 118.14, + 119.01, + 119.02, + 119.03, + 119.04, + 119.05, + 119.06, + 119.07, + 119.08, + 119.09, + 119.1, + 119.11, + 119.12, + 120.01, + 120.02, + 120.03, + 120.04, + 120.05, + 120.06, + 120.07, + 120.08, + 120.09, + 120.1, + 120.11, + 120.12, + 121.01, + 121.02, + 121.03, + 121.04, + 121.05, + 121.06, + 121.07, + 121.08, + 121.09, + 121.1, + 121.11, + 121.12, + 121.14, + 122.01, + 122.02, + 122.03, + 122.04, + 122.05, + 122.06, + 122.07, + 122.08, + 122.09, + 122.1, + 122.11, + 122.12, + 123.01, + 123.02, + 123.03, + 123.04, + 123.05, + 123.06, + 123.07, + 123.08, + 123.09, + 123.1, + 123.11, + 123.12, + 123.14, + 124.01, + 124.02, + 124.03, + 124.04, + 124.05, + 124.06, + 124.07, + 124.08, + 124.09, + 124.1, + 124.11, + 124.12, + 125.01, + 125.02, + 125.03, + 125.04, + 125.05, + 125.06, + 125.07, + 125.08, + 125.09, + 125.1, + 125.11, + 125.12, + 126.01, + 126.02, + 126.03, + 126.04, + 126.05, + 126.06, + 126.07, + 126.08, + 126.09, + 126.1, + 126.11, + 126.12, + 126.14, + 127.01, + 127.02, + 127.03, + 127.04, + 127.05, + 127.06, + 127.07, + 127.08, + 127.09, + 127.1, + 127.11, + 127.12, + 128.01, + 128.02, + 128.03, + 128.04, + 128.05, + 128.06, + 128.07, + 128.08, + 128.09, + 128.1, + 128.11, + 128.12, + 129.01, + 129.02, + 129.03, + 129.04, + 129.05, + 129.06, + 129.07, + 129.08, + 129.09, + 129.1, + 129.11, + 129.12, + 129.14, + 130.01, + 130.02, + 130.03, + 130.04, + 130.05, + 130.06, + 130.07, + 130.08, + 130.09, + 130.1, + 130.11, + 130.12, + 131.01, + 131.02, + 131.03, + 131.04, + 131.05, + 131.06, + 131.07, + 131.08, + 131.09, + 131.1, + 131.11, + 131.12, + 132.01, + 132.02, + 132.03, + 132.04, + 132.05, + 132.06, + 132.13, + 132.07, + 132.08, + 132.09, + 132.1, + 132.11, + 132.12, + 133.01, + 133.02, + 133.03, + 133.04, + 133.05, + 133.06, + 133.07, + 133.08, + 133.09, + 133.1, + 133.11, + 133.12, + 134.01, + 134.02, + 134.03, + 134.04, + 134.05, + 134.06, + 134.07, + 134.08, + 134.09, + 134.1, + 134.11, + 134.12, + 134.14, + 135.01, + 135.02, + 135.03, + 135.04, + 135.05, + 135.06, + 135.07, + 135.08, + 135.09, + 135.1, + 135.11, + 135.12, + 136.01, + 136.02, + 136.03, + 136.04, + 136.05, + 136.06, + 136.07, + 136.08, + 136.09, + 136.1, + 136.11, + 136.12, + 137.01, + 137.02, + 137.03, + 137.04, + 137.05, + 137.06, + 137.07, + 137.08, + 137.09, + 137.1, + 137.11, + 137.12, + 137.14, + 138.01, + 138.02, + 138.03, + 138.04, + 138.05, + 138.06, + 138.07, + 138.08, + 138.09, + 138.1, + 138.11, + 138.12, + 139.01, + 139.02, + 139.03, + 139.04, + 139.05, + 139.06, + 139.07, + 139.08, + 139.09, + 139.1, + 139.11, + 139.12, + 140.01, + 140.02, + 140.03, + 140.04, + 140.05, + 140.06, + 140.07, + 140.08, + 140.09, + 140.1, + 140.11, + 140.12, + 140.14, + 141.01, + 141.02, + 141.03, + 141.04, + 141.05, + 141.06, + 141.07, + 141.08, + 141.09, + 141.1, + 141.11, + 141.12, + 142.01, + 142.02, + 142.03, + 142.04, + 142.05, + 142.06, + 142.07, + 142.08, + 142.09, + 142.1, + 142.11, + 142.12, + 142.14, + 143.01, + 143.02, + 143.03, + 143.04, + 143.05, + 143.06, + 143.07, + 143.08, + 143.09, + 143.1, + 143.11, + 143.12, + 144.01, + 144.02, + 144.03, + 144.04, + 144.05, + 144.06, + 144.07, + 144.08, + 144.09, + 144.1, + 144.11, + 144.12, + 145.01, + 145.02, + 145.03, + 145.04, + 145.05, + 145.06, + 145.07, + 145.08, + 145.09, + 145.1, + 145.11, + 145.12, + 145.14, + 146.01, + 146.02, + 146.03, + 146.04, + 146.05, + 146.06, + 146.07, + 146.08, + 146.09, + 146.1, + 146.11, + 146.12, + 147.01, + 147.02, + 147.03, + 147.04, + 147.05, + 147.06, + 147.07, + 147.08, + 147.09, + 147.1, + 147.11, + 147.12, + 148.01, + 148.02, + 148.03, + 148.04, + 148.05, + 148.06, + 148.07, + 148.08, + 148.09, + 148.1, + 148.11, + 148.12, + 148.14, + 149.01, + 149.02, + 149.03, + 149.04, + 149.05, + 149.06, + 149.07, + 149.08, + 149.09, + 149.1, + 149.11, + 149.12, + 150.01, + 150.02, + 150.03, + 150.04, + 150.05, + 150.06, + 150.07, + 150.08, + 150.09, + 150.1, + 150.11, + 150.12, + 151.01, + 151.02, + 151.03, + 151.04, + 151.05, + 151.06, + 151.13, + 151.07, + 151.08, + 151.09, + 151.1, + 151.11, + 151.12, + 152.01, + 152.02, + 152.03, + 152.04, + 152.05, + 152.06, + 152.07, + 152.08, + 152.09, + 152.1, + 152.11, + 152.12, + 153.01, + 153.02, + 153.03, + 153.04, + 153.05, + 153.06, + 153.07, + 153.08, + 153.09, + 153.1, + 153.11, + 153.12, + 153.14, + 154.01, + 154.02, + 154.03, + 154.04, + 154.05, + 154.06, + 154.07, + 154.08, + 154.09, + 154.1, + 154.11, + 154.12, + 155.01, + 155.02, + 155.03, + 155.04, + 155.05, + 155.06, + 155.07, + 155.08, + 155.09, + 155.1, + 155.11, + 155.12, + 156.01, + 156.02, + 156.03, + 156.04, + 156.05, + 156.06, + 156.07, + 156.08, + 156.09, + 156.1, + 156.11, + 156.12, + 156.14, + 157.01, + 157.02, + 157.03, + 157.04, + 157.05, + 157.06, + 157.07, + 157.08, + 157.09, + 157.1, + 157.11, + 157.12, + 158.01, + 158.02, + 158.03, + 158.04, + 158.05, + 158.06, + 158.07, + 158.08, + 158.09, + 158.1, + 158.11, + 158.12, + 159.01, + 159.02, + 159.03, + 159.04, + 159.05, + 159.06, + 159.07, + 159.08, + 159.09, + 159.1, + 159.11, + 159.12, + 159.14, + 160.01, + 160.02, + 160.03, + 160.04, + 160.05, + 160.06, + 160.07, + 160.08, + 160.09, + 160.1, + 160.11, + 160.12, + 161.01, + 161.02, + 161.03, + 161.04, + 161.05, + 161.06, + 161.07, + 161.08, + 161.09, + 161.1, + 161.11, + 161.12, + 161.14, + 162.01, + 162.02, + 162.03, + 162.04, + 162.05, + 162.06, + 162.07, + 162.08, + 162.09, + 162.1, + 162.11, + 162.12, + 163.01, + 163.02, + 163.03, + 163.04, + 163.05, + 163.06, + 163.07, + 163.08, + 163.09, + 163.1, + 163.11, + 163.12, + 164.01, + 164.02, + 164.03, + 164.04, + 164.05, + 164.06, + 164.07, + 164.08, + 164.09, + 164.1, + 164.11, + 164.12, + 164.14, + 165.01, + 165.02, + 165.03, + 165.04, + 165.05, + 165.06, + 165.07, + 165.08, + 165.09, + 165.1, + 165.11, + 165.12, + 166.01, + 166.02, + 166.03, + 166.04, + 166.05, + 166.06, + 166.07, + 166.08, + 166.09, + 166.1, + 166.11, + 166.12, + 167.01, + 167.02, + 167.03, + 167.04, + 167.05, + 167.06, + 167.07, + 167.08, + 167.09, + 167.1, + 167.11, + 167.12, + 167.14, + 168.01, + 168.02, + 168.03, + 168.04, + 168.05, + 168.06, + 168.07, + 168.08, + 168.09, + 168.1, + 168.11, + 168.12, + 169.01, + 169.02, + 169.03, + 169.04, + 169.05, + 169.06, + 169.07, + 169.08, + 169.09, + 169.1, + 169.11, + 169.12, + 170.01, + 170.02, + 170.03, + 170.04, + 170.05, + 170.06, + 170.13, + 170.07, + 170.08, + 170.09, + 170.1, + 170.11, + 170.12, + 171.01, + 171.02, + 171.03, + 171.04, + 171.05, + 171.06, + 171.07, + 171.08, + 171.09, + 171.1, + 171.11, + 171.12, + 172.01, + 172.02, + 172.03, + 172.04, + 172.05, + 172.06, + 172.07, + 172.08, + 172.09, + 172.1, + 172.11, + 172.12, + 172.14, + 173.01, + 173.02, + 173.03, + 173.04, + 173.05, + 173.06, + 173.07, + 173.08, + 173.09, + 173.1, + 173.11, + 173.12, + 174.01, + 174.02, + 174.03, + 174.04, + 174.05, + 174.06, + 174.07, + 174.08, + 174.09, + 174.1, + 174.11, + 174.12, + 175.01, + 175.02, + 175.03, + 175.04, + 175.05, + 175.06, + 175.07, + 175.08, + 175.09, + 175.1, + 175.11, + 175.12, + 175.14, + 176.01, + 176.02, + 176.03, + 176.04, + 176.05, + 176.06, + 176.07, + 176.08, + 176.09, + 176.1, + 176.11, + 176.12, + 177.01, + 177.02, + 177.03, + 177.04, + 177.05, + 177.06, + 177.07, + 177.08, + 177.09, + 177.1, + 177.11, + 177.12, + 178.01, + 178.02, + 178.03, + 178.04, + 178.05, + 178.06, + 178.07, + 178.08, + 178.09, + 178.1, + 178.11, + 178.12, + 178.14, + 179.01, + 179.02, + 179.03, + 179.04, + 179.05, + 179.06, + 179.07, + 179.08, + 179.09, + 179.1, + 179.11, + 179.12, + 180.01, + 180.02, + 180.03, + 180.04, + 180.05, + 180.06, + 180.07, + 180.08, + 180.09, + 180.1, + 180.11, + 180.12, + 180.14, + 181.01, + 181.02, + 181.03, + 181.04, + 181.05, + 181.06, + 181.07, + 181.08, + 181.09, + 181.1, + 181.11, + 181.12, + 182.01, + 182.02, + 182.03, + 182.04, + 182.05, + 182.06, + 182.07, + 182.08, + 182.09, + 182.1, + 182.11, + 182.12, + 183.01, + 183.02, + 183.03, + 183.04, + 183.05, + 183.06, + 183.07, + 183.08, + 183.09, + 183.1, + 183.11, + 183.12, + 183.14, + 184.01, + 184.02, + 184.03, + 184.04, + 184.05, + 184.06, + 184.07, + 184.08, + 184.09, + 184.1, + 184.11, + 184.12, + 185.01, + 185.02, + 185.03, + 185.04, + 185.05, + 185.06, + 185.07, + 185.08, + 185.09, + 185.1, + 185.11, + 185.12, + 186.01, + 186.02, + 186.03, + 186.04, + 186.05, + 186.06, + 186.07, + 186.08, + 186.09, + 186.1, + 186.11, + 186.12, + 186.14, + 187.01, + 187.02, + 187.03, + 187.04, + 187.05, + 187.06, + 187.07, + 187.08, + 187.09, + 187.1, + 187.11, + 187.12, + 188.01, + 188.02, + 188.03, + 188.04, + 188.05, + 188.06, + 188.07, + 188.08, + 188.09, + 188.1, + 188.11, + 188.12, + 189.01, + 189.02, + 189.03, + 189.04, + 189.05, + 189.06, + 189.13, + 189.07, + 189.08, + 189.09, + 189.1, + 189.11, + 189.12, + 190.01, + 190.02, + 190.03, + 190.04, + 190.05, + 190.06, + 190.07, + 190.08, + 190.09, + 190.1, + 190.11, + 190.12, + 191.01, + 191.02, + 191.03, + 191.04, + 191.05, + 191.06, + 191.07, + 191.08, + 191.09, + 191.1, + 191.11, + 191.12, + 191.14, + 192.01, + 192.02, + 192.03, + 192.04, + 192.05, + 192.06, + 192.07, + 192.08, + 192.09, + 192.1, + 192.11, + 192.12, + 193.01, + 193.02, + 193.03, + 193.04, + 193.05, + 193.06, + 193.07, + 193.08, + 193.09, + 193.1, + 193.11, + 193.12, + 194.01, + 194.02, + 194.03, + 194.04, + 194.05, + 194.06, + 194.07, + 194.08, + 194.09, + 194.1, + 194.11, + 194.12, + 194.14, + 195.01, + 195.02, + 195.03, + 195.04, + 195.05, + 195.06, + 195.07, + 195.08, + 195.09, + 195.1, + 195.11, + 195.12, + 196.01, + 196.02, + 196.03, + 196.04, + 196.05, + 196.06, + 196.07, + 196.08, + 196.09, + 196.1, + 196.11, + 196.12, + 197.01, + 197.02, + 197.03, + 197.04, + 197.05, + 197.06, + 197.07, + 197.08, + 197.09, + 197.1, + 197.11, + 197.12, + 197.14, + 198.01, + 198.02, + 198.03, + 198.04, + 198.05, + 198.06, + 198.07, + 198.08, + 198.09, + 198.1, + 198.11, + 198.12, + 199.01, + 199.02, + 199.03, + 199.04, + 199.05, + 199.06, + 199.07, + 199.08, + 199.09, + 199.1, + 199.11, + 199.12, + 199.14, + 200.01, + 200.02, + 200.03, + 200.04, + 200.05, + 200.06, + 200.07, + 200.08, + 200.09, + 200.1, + 200.11, + 200.12, + 201.01, + 201.02, + 201.03, + 201.04, + 201.05, + 201.06, + 201.07, + 201.08, + 201.09, + 201.1, + 201.11, + 201.12, + 202.01, + 202.02, + 202.03, + 202.04, + 202.05, + 202.06, + 202.07, + 202.08, + 202.09, + 202.1, + 202.11, + 202.12, + 202.14, + 203.01, + 203.02, + 203.03, + 203.04, + 203.05, + 203.06, + 203.07, + 203.08, + 203.09, + 203.1, + 203.11, + 203.12, + 204.01, + 204.02, + 204.03, + 204.04, + 204.05, + 204.06, + 204.07, + 204.08, + 204.09, + 204.1, + 204.11, + 204.12, + 205.01, + 205.02, + 205.03, + 205.04, + 205.05, + 205.06, + 205.07, + 205.08, + 205.09, + 205.1, + 205.11, + 205.12, + 205.14, + 206.01, + 206.02, + 206.03, + 206.04, + 206.05, + 206.06, + 206.07, + 206.08, + 206.09, + 206.1, + 206.11, + 206.12, + 207.01, + 207.02, + 207.03, + 207.04, + 207.05, + 207.06, + 207.07, + 207.08, + 207.09, + 207.1, + 207.11, + 207.12, + 208.01, + 208.02, + 208.03, + 208.04, + 208.05, + 208.06, + 208.13, + 208.07, + 208.08, + 208.09, + 208.1, + 208.11, + 208.12, + 209.01, + 209.02, + 209.03, + 209.04, + 209.05, + 209.06, + 209.07, + 209.08, + 209.09, + 209.1, + 209.11, + 209.12, + 210.01, + 210.02, + 210.03, + 210.04, + 210.05, + 210.06, + 210.07, + 210.08, + 210.09, + 210.1, + 210.11, + 210.12, + 210.14, + 211.01, + 211.02, + 211.03, + 211.04, + 211.05, + 211.06, + 211.07, + 211.08, + 211.09, + 211.1, + 211.11, + 211.12, + 212.01, + 212.02, + 212.03, + 212.04, + 212.05, + 212.06, + 212.07, + 212.08, + 212.09, + 212.1, + 212.11, + 212.12, + 213.01, + 213.02, + 213.03, + 213.04, + 213.05, + 213.06, + 213.07, + 213.08, + 213.09, + 213.1, + 213.11, + 213.12, + 213.14, + 214.01, + 214.02, + 214.03, + 214.04, + 214.05, + 214.06, + 214.07, + 214.08, + 214.09, + 214.1, + 214.11, + 214.12, + 215.01, + 215.02, + 215.03, + 215.04, + 215.05, + 215.06, + 215.07, + 215.08, + 215.09, + 215.1, + 215.11, + 215.12, + 216.01, + 216.02, + 216.03, + 216.04, + 216.05, + 216.06, + 216.07, + 216.08, + 216.09, + 216.1, + 216.11, + 216.12, + 216.14, + 217.01, + 217.02, + 217.03, + 217.04, + 217.05, + 217.06, + 217.07, + 217.08, + 217.09, + 217.1, + 217.11, + 217.12, + 218.01, + 218.02, + 218.03, + 218.04, + 218.05, + 218.06, + 218.07, + 218.08, + 218.09, + 218.1, + 218.11, + 218.12, + 218.14, + 219.01, + 219.02, + 219.03, + 219.04, + 219.05, + 219.06, + 219.07, + 219.08, + 219.09, + 219.1, + 219.11, + 219.12, + 220.01, + 220.02, + 220.03, + 220.04, + 220.05, + 220.06, + 220.07, + 220.08, + 220.09, + 220.1, + 220.11, + 220.12, + 221.01, + 221.02, + 221.03, + 221.04, + 221.05, + 221.06, + 221.07, + 221.08, + 221.09, + 221.1, + 221.11, + 221.12, + 221.14, + 222.01, + 222.02, + 222.03, + 222.04, + 222.05, + 222.06, + 222.07, + 222.08, + 222.09, + 222.1, + 222.11, + 222.12, + 223.01, + 223.02, + 223.03, + 223.04, + 223.05, + 223.06, + 223.07, + 223.08, + 223.09, + 223.1, + 223.11, + 223.12, + 224.01, + 224.02, + 224.03, + 224.04, + 224.05, + 224.06, + 224.07, + 224.08, + 224.09, + 224.1, + 224.11, + 224.12, + 224.14, + 225.01, + 225.02, + 225.03, + 225.04, + 225.05, + 225.06, + 225.07, + 225.08, + 225.09, + 225.1, + 225.11, + 225.12, + 226.01, + 226.02, + 226.03, + 226.04, + 226.05, + 226.06, + 226.07, + 226.08, + 226.09, + 226.1, + 226.11, + 226.12, + 227.01, + 227.02, + 227.03, + 227.04, + 227.05, + 227.06, + 227.13, + 227.07, + 227.08, + 227.09, + 227.1, + 227.11, + 227.12, + 228.01, + 228.02, + 228.03, + 228.04, + 228.05, + 228.06, + 228.07, + 228.08, + 228.09, + 228.1, + 228.11, + 228.12, + 229.01, + 229.02, + 229.03, + 229.04, + 229.05, + 229.06, + 229.07, + 229.08, + 229.09, + 229.1, + 229.11, + 229.12, + 229.14, + 230.01, + 230.02, + 230.03, + 230.04, + 230.05, + 230.06, + 230.07, + 230.08, + 230.09, + 230.1, + 230.11, + 230.12, + 231.01, + 231.02, + 231.03, + 231.04, + 231.05, + 231.06, + 231.07, + 231.08, + 231.09, + 231.1, + 231.11, + 231.12, + 232.01, + 232.02, + 232.03, + 232.04, + 232.05, + 232.06, + 232.07, + 232.08, + 232.09, + 232.1, + 232.11, + 232.12, + 232.14, + 233.01, + 233.02, + 233.03, + 233.04, + 233.05, + 233.06, + 233.07, + 233.08, + 233.09, + 233.1, + 233.11, + 233.12, + 234.01, + 234.02, + 234.03, + 234.04, + 234.05, + 234.06, + 234.07, + 234.08, + 234.09, + 234.1, + 234.11, + 234.12, + 235.01, + 235.02, + 235.03, + 235.04, + 235.05, + 235.06, + 235.07, + 235.08, + 235.09, + 235.1, + 235.11, + 235.12, + 235.14, + 236.01, + 236.02, + 236.03, + 236.04, + 236.05, + 236.06, + 236.07, + 236.08, + 236.09, + 236.1, + 236.11, + 236.12, + 237.01, + 237.02, + 237.03, + 237.04, + 237.05, + 237.06, + 237.07, + 237.08, + 237.09, + 237.1, + 237.11, + 237.12, + 237.14, + 238.01, + 238.02, + 238.03, + 238.04, + 238.05, + 238.06, + 238.07, + 238.08, + 238.09, + 238.1, + 238.11, + 238.12, + 239.01, + 239.02, + 239.03, + 239.04, + 239.05, + 239.06, + 239.07, + 239.08, + 239.09, + 239.1, + 239.11, + 239.12, + 240.01, + 240.02, + 240.03, + 240.04, + 240.05, + 240.06, + 240.07, + 240.08, + 240.09, + 240.1, + 240.11, + 240.12, + 240.14, + 241.01, + 241.02, + 241.03, + 241.04, + 241.05, + 241.06, + 241.07, + 241.08, + 241.09, + 241.1, + 241.11, + 241.12, + 242.01, + 242.02, + 242.03, + 242.04, + 242.05, + 242.06, + 242.07, + 242.08, + 242.09, + 242.1, + 242.11, + 242.12, + 243.01, + 243.02, + 243.03, + 243.04, + 243.05, + 243.06, + 243.07, + 243.08, + 243.09, + 243.1, + 243.11, + 243.12, + 243.14, + 244.01, + 244.02, + 244.03, + 244.04, + 244.05, + 244.06, + 244.07, + 244.08, + 244.09, + 244.1, + 244.11, + 244.12, + 245.01, + 245.02, + 245.03, + 245.04, + 245.05, + 245.06, + 245.07, + 245.08, + 245.09, + 245.1, + 245.11, + 245.12, + 246.01, + 246.02, + 246.03, + 246.04, + 246.05, + 246.06, + 246.13, + 246.07, + 246.08, + 246.09, + 246.1, + 246.11, + 246.12, + 247.01, + 247.02, + 247.03, + 247.04, + 247.05, + 247.06, + 247.07, + 247.08, + 247.09, + 247.1, + 247.11, + 247.12, + 248.01, + 248.02, + 248.03, + 248.04, + 248.05, + 248.06, + 248.07, + 248.08, + 248.09, + 248.1, + 248.11, + 248.12, + 248.14, + 249.01, + 249.02, + 249.03, + 249.04, + 249.05, + 249.06, + 249.07, + 249.08, + 249.09, + 249.1, + 249.11, + 249.12, + 250.01, + 250.02, + 250.03, + 250.04, + 250.05, + 250.06, + 250.07, + 250.08, + 250.09, + 250.1, + 250.11, + 250.12, + 251.01, + 251.02, + 251.03, + 251.04, + 251.05, + 251.06, + 251.07, + 251.08, + 251.09, + 251.1, + 251.11, + 251.12, + 251.14, + 252.01, + 252.02, + 252.03, + 252.04, + 252.05, + 252.06, + 252.07, + 252.08, + 252.09, + 252.1, + 252.11, + 252.12, + 253.01, + 253.02, + 253.03, + 253.04, + 253.05, + 253.06, + 253.07, + 253.08, + 253.09, + 253.1, + 253.11, + 253.12, + 254.01, + 254.02, + 254.03, + 254.04, + 254.05, + 254.06, + 254.07, + 254.08, + 254.09, + 254.1, + 254.11, + 254.12, + 254.14, + 255.01, + 255.02, + 255.03, + 255.04, + 255.05, + 255.06, + 255.07, + 255.08, + 255.09, + 255.1, + 255.11, + 255.12, + 256.01, + 256.02, + 256.03, + 256.04, + 256.05, + 256.06, + 256.07, + 256.08, + 256.09, + 256.1, + 256.11, + 256.12, + 256.14, + 257.01, + 257.02, + 257.03, + 257.04, + 257.05, + 257.06, + 257.07, + 257.08, + 257.09, + 257.1, + 257.11, + 257.12, + 258.01, + 258.02, + 258.03, + 258.04, + 258.05, + 258.06, + 258.07, + 258.08, + 258.09, + 258.1, + 258.11, + 258.12, + 259.01, + 259.02, + 259.03, + 259.04, + 259.05, + 259.06, + 259.07, + 259.08, + 259.09, + 259.1, + 259.11, + 259.12, + 259.14, + 260.01, + 260.02, + 260.03, + 260.04, + 260.05, + 260.06, + 260.07, + 260.08, + 260.09, + 260.1, + 260.11, + 260.12, + 261.01, + 261.02, + 261.03, + 261.04, + 261.05, + 261.06, + 261.07, + 261.08, + 261.09, + 261.1, + 261.11, + 261.12, + 262.01, + 262.02, + 262.03, + 262.04, + 262.05, + 262.06, + 262.07, + 262.08, + 262.09, + 262.1, + 262.11, + 262.12, + 262.14, + 263.01, + 263.02, + 263.03, + 263.04, + 263.05, + 263.06, + 263.07, + 263.08, + 263.09, + 263.1, + 263.11, + 263.12, + 264.01, + 264.02, + 264.03, + 264.04, + 264.05, + 264.06, + 264.07, + 264.08, + 264.09, + 264.1, + 264.11, + 264.12, + 265.01, + 265.02, + 265.03, + 265.04, + 265.05, + 265.06, + 265.13, + 265.07, + 265.08, + 265.09, + 265.1, + 265.11, + 265.12, + 266.01, + 266.02, + 266.03, + 266.04, + 266.05, + 266.06, + 266.07, + 266.08, + 266.09, + 266.1, + 266.11, + 266.12, + 267.01, + 267.02, + 267.03, + 267.04, + 267.05, + 267.06, + 267.07, + 267.08, + 267.09, + 267.1, + 267.11, + 267.12, + 267.14, + 268.01, + 268.02, + 268.03, + 268.04, + 268.05, + 268.06, + 268.07, + 268.08, + 268.09, + 268.1, + 268.11, + 268.12, + 269.01, + 269.02, + 269.03, + 269.04, + 269.05, + 269.06, + 269.07, + 269.08, + 269.09, + 269.1, + 269.11, + 269.12, + 270.01, + 270.02, + 270.03, + 270.04, + 270.05, + 270.06, + 270.07, + 270.08, + 270.09, + 270.1, + 270.11, + 270.12, + 270.14, + 271.01, + 271.02, + 271.03, + 271.04, + 271.05, + 271.06, + 271.07, + 271.08, + 271.09, + 271.1, + 271.11, + 271.12, + 272.01, + 272.02, + 272.03, + 272.04, + 272.05, + 272.06, + 272.07, + 272.08, + 272.09, + 272.1, + 272.11, + 272.12, + 273.01, + 273.02, + 273.03, + 273.04, + 273.05, + 273.06, + 273.07, + 273.08, + 273.09, + 273.1, + 273.11, + 273.12, + 273.14, + 274.01, + 274.02, + 274.03, + 274.04, + 274.05, + 274.06, + 274.07, + 274.08, + 274.09, + 274.1, + 274.11, + 274.12, + 275.01, + 275.02, + 275.03, + 275.04, + 275.05, + 275.06, + 275.07, + 275.08, + 275.09, + 275.1, + 275.11, + 275.12, + 275.14, + 276.01, + 276.02, + 276.03, + 276.04, + 276.05, + 276.06, + 276.07, + 276.08, + 276.09, + 276.1, + 276.11, + 276.12, + 277.01, + 277.02, + 277.03, + 277.04, + 277.05, + 277.06, + 277.07, + 277.08, + 277.09, + 277.1, + 277.11, + 277.12, + 278.01, + 278.02, + 278.03, + 278.04, + 278.05, + 278.06, + 278.07, + 278.08, + 278.09, + 278.1, + 278.11, + 278.12, + 278.14, + 279.01, + 279.02, + 279.03, + 279.04, + 279.05, + 279.06, + 279.07, + 279.08, + 279.09, + 279.1, + 279.11, + 279.12, + 280.01, + 280.02, + 280.03, + 280.04, + 280.05, + 280.06, + 280.07, + 280.08, + 280.09, + 280.1, + 280.11, + 280.12, + 281.01, + 281.02, + 281.03, + 281.04, + 281.05, + 281.06, + 281.07, + 281.08, + 281.09, + 281.1, + 281.11, + 281.12, + 281.14, + 282.01, + 282.02, + 282.03, + 282.04, + 282.05, + 282.06, + 282.07, + 282.08, + 282.09, + 282.1, + 282.11, + 282.12, + 283.01, + 283.02, + 283.03, + 283.04, + 283.05, + 283.06, + 283.07, + 283.08, + 283.09, + 283.1, + 283.11, + 283.12, + 284.01, + 284.02, + 284.03, + 284.04, + 284.05, + 284.06, + 284.13, + 284.07, + 284.08, + 284.09, + 284.1, + 284.11, + 284.12, + 285.01, + 285.02, + 285.03, + 285.04, + 285.05, + 285.06, + 285.07, + 285.08, + 285.09, + 285.1, + 285.11, + 285.12, + 286.01, + 286.02, + 286.03, + 286.04, + 286.05, + 286.06, + 286.07, + 286.08, + 286.09, + 286.1, + 286.11, + 286.12, + 286.14, + 287.01, + 287.02, + 287.03, + 287.04, + 287.05, + 287.06, + 287.07, + 287.08, + 287.09, + 287.1, + 287.11, + 287.12, + 288.01, + 288.02, + 288.03, + 288.04, + 288.05, + 288.06, + 288.07, + 288.08, + 288.09, + 288.1, + 288.11, + 288.12, + 289.01, + 289.02, + 289.03, + 289.04, + 289.05, + 289.06, + 289.07, + 289.08, + 289.09, + 289.1, + 289.11, + 289.12, + 289.14, + 290.01, + 290.02, + 290.03, + 290.04, + 290.05, + 290.06, + 290.07, + 290.08, + 290.09, + 290.1, + 290.11, + 290.12, + 291.01, + 291.02, + 291.03, + 291.04, + 291.05, + 291.06, + 291.07, + 291.08, + 291.09, + 291.1, + 291.11, + 291.12, + 292.01, + 292.02, + 292.03, + 292.04, + 292.05, + 292.06, + 292.07, + 292.08, + 292.09, + 292.1, + 292.11, + 292.12, + 292.14, + 293.01, + 293.02, + 293.03, + 293.04, + 293.05, + 293.06, + 293.07, + 293.08, + 293.09, + 293.1, + 293.11, + 293.12, + 294.01, + 294.02, + 294.03, + 294.04, + 294.05, + 294.06, + 294.07, + 294.08, + 294.09, + 294.1, + 294.11, + 294.12, + 294.14, + 295.01, + 295.02, + 295.03, + 295.04, + 295.05, + 295.06, + 295.07, + 295.08, + 295.09, + 295.1, + 295.11, + 295.12, + 296.01, + 296.02, + 296.03, + 296.04, + 296.05, + 296.06, + 296.07, + 296.08, + 296.09, + 296.1, + 296.11, + 296.12, + 297.01, + 297.02, + 297.03, + 297.04, + 297.05, + 297.06, + 297.07, + 297.08, + 297.09, + 297.1, + 297.11, + 297.12, + 297.14, + 298.01, + 298.02, + 298.03, + 298.04, + 298.05, + 298.06, + 298.07, + 298.08, + 298.09, + 298.1, + 298.11, + 298.12, + 299.01, + 299.02, + 299.03, + 299.04, + 299.05, + 299.06, + 299.07, + 299.08, + 299.09, + 299.1, + 299.11, + 299.12, + 300.01, + 300.02, + 300.03, + 300.04, + 300.05, + 300.06, + 300.07, + 300.08, + 300.09, + 300.1, + 300.11, + 300.12, + 300.14, + 301.01, + 301.02, + 301.03, + 301.04, + 301.05, + 301.06, + 301.07, + 301.08, + 301.09, + 301.1, + 301.11, + 301.12, + 302.01, + 302.02, + 302.03, + 302.04, + 302.05, + 302.06, + 302.07, + 302.08, + 302.09, + 302.1, + 302.11, + 302.12, + 303.01, + 303.02, + 303.03, + 303.04, + 303.05, + 303.06, + 303.13, + 303.07, + 303.08, + 303.09, + 303.1, + 303.11, + 303.12, + 304.01, + 304.02, + 304.03, + 304.04, + 304.05, + 304.06, + 304.07, + 304.08, + 304.09, + 304.1, + 304.11, + 304.12, + 305.01, + 305.02, + 305.03, + 305.04, + 305.05, + 305.06, + 305.07, + 305.08, + 305.09, + 305.1, + 305.11, + 305.12, + 305.14, + 306.01, + 306.02, + 306.03, + 306.04, + 306.05, + 306.06, + 306.07, + 306.08, + 306.09, + 306.1, + 306.11, + 306.12, + 307.01, + 307.02, + 307.03, + 307.04, + 307.05, + 307.06, + 307.07, + 307.08, + 307.09, + 307.1, + 307.11, + 307.12, + 308.01, + 308.02, + 308.03, + 308.04, + 308.05, + 308.06, + 308.07, + 308.08, + 308.09, + 308.1, + 308.11, + 308.12, + 308.14, + 309.01, + 309.02, + 309.03, + 309.04, + 309.05, + 309.06, + 309.07, + 309.08, + 309.09, + 309.1, + 309.11, + 309.12, + 310.01, + 310.02, + 310.03, + 310.04, + 310.05, + 310.06, + 310.07, + 310.08, + 310.09, + 310.1, + 310.11, + 310.12, + 311.01, + 311.02, + 311.03, + 311.04, + 311.05, + 311.06, + 311.07, + 311.08, + 311.09, + 311.1, + 311.11, + 311.12, + 311.14, + 312.01, + 312.02, + 312.03, + 312.04, + 312.05, + 312.06, + 312.07, + 312.08, + 312.09, + 312.1, + 312.11, + 312.12, + 313.01, + 313.02, + 313.03, + 313.04, + 313.05, + 313.06, + 313.07, + 313.08, + 313.09, + 313.1, + 313.11, + 313.12, + 313.14, + 314.01, + 314.02, + 314.03, + 314.04, + 314.05, + 314.06, + 314.07, + 314.08, + 314.09, + 314.1, + 314.11, + 314.12, + 315.01, + 315.02, + 315.03, + 315.04, + 315.05, + 315.06, + 315.07, + 315.08, + 315.09, + 315.1, + 315.11, + 315.12, + 316.01, + 316.02, + 316.03, + 316.04, + 316.05, + 316.06, + 316.07, + 316.08, + 316.09, + 316.1, + 316.11, + 316.12, + 316.14, + 317.01, + 317.02, + 317.03, + 317.04, + 317.05, + 317.06, + 317.07, + 317.08, + 317.09, + 317.1, + 317.11, + 317.12, + 318.01, + 318.02, + 318.03, + 318.04, + 318.05, + 318.06, + 318.07, + 318.08, + 318.09, + 318.1, + 318.11, + 318.12, + 319.01, + 319.02, + 319.03, + 319.04, + 319.05, + 319.06, + 319.07, + 319.08, + 319.09, + 319.1, + 319.11, + 319.12, + 319.14, + 320.01, + 320.02, + 320.03, + 320.04, + 320.05, + 320.06, + 320.07, + 320.08, + 320.09, + 320.1, + 320.11, + 320.12, + 321.01, + 321.02, + 321.03, + 321.04, + 321.05, + 321.06, + 321.07, + 321.08, + 321.09, + 321.1, + 321.11, + 321.12, + 322.01, + 322.02, + 322.03, + 322.04, + 322.05, + 322.06, + 322.13, + 322.07, + 322.08, + 322.09, + 322.1, + 322.11, + 322.12, + 323.01, + 323.02, + 323.03, + 323.04, + 323.05, + 323.06, + 323.07, + 323.08, + 323.09, + 323.1, + 323.11, + 323.12, + 324.01, + 324.02, + 324.03, + 324.04, + 324.05, + 324.06, + 324.07, + 324.08, + 324.09, + 324.1, + 324.11, + 324.12, + 324.14, + 325.01, + 325.02, + 325.03, + 325.04, + 325.05, + 325.06, + 325.07, + 325.08, + 325.09, + 325.1, + 325.11, + 325.12, + 326.01, + 326.02, + 326.03, + 326.04, + 326.05, + 326.06, + 326.07, + 326.08, + 326.09, + 326.1, + 326.11, + 326.12, + 327.01, + 327.02, + 327.03, + 327.04, + 327.05, + 327.06, + 327.07, + 327.08, + 327.09, + 327.1, + 327.11, + 327.12, + 327.14, + 328.01, + 328.02, + 328.03, + 328.04, + 328.05, + 328.06, + 328.07, + 328.08, + 328.09, + 328.1, + 328.11, + 328.12, + 329.01, + 329.02, + 329.03, + 329.04, + 329.05, + 329.06, + 329.07, + 329.08, + 329.09, + 329.1, + 329.11, + 329.12, + 330.01, + 330.02, + 330.03, + 330.04, + 330.05, + 330.06, + 330.07, + 330.08, + 330.09, + 330.1, + 330.11, + 330.12, + 330.14, + 331.01, + 331.02, + 331.03, + 331.04, + 331.05, + 331.06, + 331.07, + 331.08, + 331.09, + 331.1, + 331.11, + 331.12, + 332.01, + 332.02, + 332.03, + 332.04, + 332.05, + 332.06, + 332.07, + 332.08, + 332.09, + 332.1, + 332.11, + 332.12, + 332.14, + 333.01, + 333.02, + 333.03, + 333.04, + 333.05, + 333.06, + 333.07, + 333.08, + 333.09, + 333.1, + 333.11, + 333.12, + 334.01, + 334.02, + 334.03, + 334.04, + 334.05, + 334.06, + 334.07, + 334.08, + 334.09, + 334.1, + 334.11, + 334.12, + 335.01, + 335.02, + 335.03, + 335.04, + 335.05, + 335.06, + 335.07, + 335.08, + 335.09, + 335.1, + 335.11, + 335.12, + 335.14, + 336.01, + 336.02, + 336.03, + 336.04, + 336.05, + 336.06, + 336.07, + 336.08, + 336.09, + 336.1, + 336.11, + 336.12, + 337.01, + 337.02, + 337.03, + 337.04, + 337.05, + 337.06, + 337.07, + 337.08, + 337.09, + 337.1, + 337.11, + 337.12, + 338.01, + 338.02, + 338.03, + 338.04, + 338.05, + 338.06, + 338.07, + 338.08, + 338.09, + 338.1, + 338.11, + 338.12, + 338.14, + 339.01, + 339.02, + 339.03, + 339.04, + 339.05, + 339.06, + 339.07, + 339.08, + 339.09, + 339.1, + 339.11, + 339.12, + 340.01, + 340.02, + 340.03, + 340.04, + 340.05, + 340.06, + 340.07, + 340.08, + 340.09, + 340.1, + 340.11, + 340.12, + 341.01, + 341.02, + 341.03, + 341.04, + 341.05, + 341.06, + 341.13, + 341.07, + 341.08, + 341.09, + 341.1, + 341.11, + 341.12, + 342.01, + 342.02, + 342.03, + 342.04, + 342.05, + 342.06, + 342.07, + 342.08, + 342.09, + 342.1, + 342.11, + 342.12, + 343.01, + 343.02, + 343.03, + 343.04, + 343.05, + 343.06, + 343.07, + 343.08, + 343.09, + 343.1, + 343.11, + 343.12, + 343.14, + 344.01, + 344.02, + 344.03, + 344.04, + 344.05, + 344.06, + 344.07, + 344.08, + 344.09, + 344.1, + 344.11, + 344.12, + 345.01, + 345.02, + 345.03, + 345.04, + 345.05, + 345.06, + 345.07, + 345.08, + 345.09, + 345.1, + 345.11, + 345.12, + 346.01, + 346.02, + 346.03, + 346.04, + 346.05, + 346.06, + 346.07, + 346.08, + 346.09, + 346.1, + 346.11, + 346.12, + 346.14, + 347.01, + 347.02, + 347.03, + 347.04, + 347.05, + 347.06, + 347.07, + 347.08, + 347.09, + 347.1, + 347.11, + 347.12, + 348.01, + 348.02, + 348.03, + 348.04, + 348.05, + 348.06, + 348.07, + 348.08, + 348.09, + 348.1, + 348.11, + 348.12, + 349.01, + 349.02, + 349.03, + 349.04, + 349.05, + 349.06, + 349.07, + 349.08, + 349.09, + 349.1, + 349.11, + 349.12, + 349.14, + 350.01, + 350.02, + 350.03, + 350.04, + 350.05, + 350.06, + 350.07, + 350.08, + 350.09, + 350.1, + 350.11, + 350.12, + 351.01, + 351.02, + 351.03, + 351.04, + 351.05, + 351.06, + 351.07, + 351.08, + 351.09, + 351.1, + 351.11, + 351.12, + 351.14, + 352.01, + 352.02, + 352.03, + 352.04, + 352.05, + 352.06, + 352.07, + 352.08, + 352.09, + 352.1, + 352.11, + 352.12, + 353.01, + 353.02, + 353.03, + 353.04, + 353.05, + 353.06, + 353.07, + 353.08, + 353.09, + 353.1, + 353.11, + 353.12, + 354.01, + 354.02, + 354.03, + 354.04, + 354.05, + 354.06, + 354.07, + 354.08, + 354.09, + 354.1, + 354.11, + 354.12, + 354.14, + 355.01, + 355.02, + 355.03, + 355.04, + 355.05, + 355.06, + 355.07, + 355.08, + 355.09, + 355.1, + 355.11, + 355.12, + 356.01, + 356.02, + 356.03, + 356.04, + 356.05, + 356.06, + 356.07, + 356.08, + 356.09, + 356.1, + 356.11, + 356.12, + 357.01, + 357.02, + 357.03, + 357.04, + 357.05, + 357.06, + 357.07, + 357.08, + 357.09, + 357.1, + 357.11, + 357.12, + 357.14, + 358.01, + 358.02, + 358.03, + 358.04, + 358.05, + 358.06, + 358.07, + 358.08, + 358.09, + 358.1, + 358.11, + 358.12, + 359.01, + 359.02, + 359.03, + 359.04, + 359.05, + 359.06, + 359.07, + 359.08, + 359.09, + 359.1, + 359.11, + 359.12, + 360.01, + 360.02, + 360.03, + 360.04, + 360.05, + 360.06, + 360.13, + 360.07, + 360.08, + 360.09, + 360.1, + 360.11, + 360.12, + 361.01, + 361.02, + 361.03, + 361.04, + 361.05, + 361.06, + 361.07, + 361.08, + 361.09, + 361.1, + 361.11, + 361.12, + 362.01, + 362.02, + 362.03, + 362.04, + 362.05, + 362.06, + 362.07, + 362.08, + 362.09, + 362.1, + 362.11, + 362.12, + 362.14, + 363.01, + 363.02, + 363.03, + 363.04, + 363.05, + 363.06, + 363.07, + 363.08, + 363.09, + 363.1, + 363.11, + 363.12, + 364.01, + 364.02, + 364.03, + 364.04, + 364.05, + 364.06, + 364.07, + 364.08, + 364.09, + 364.1, + 364.11, + 364.12, + 365.01, + 365.02, + 365.03, + 365.04, + 365.05, + 365.06, + 365.07, + 365.08, + 365.09, + 365.1, + 365.11, + 365.12, + 365.14, + 366.01, + 366.02, + 366.03, + 366.04, + 366.05, + 366.06, + 366.07, + 366.08, + 366.09, + 366.1, + 366.11, + 366.12, + 367.01, + 367.02, + 367.03, + 367.04, + 367.05, + 367.06, + 367.07, + 367.08, + 367.09, + 367.1, + 367.11, + 367.12, + 368.01, + 368.02, + 368.03, + 368.04, + 368.05, + 368.06, + 368.07, + 368.08, + 368.09, + 368.1, + 368.11, + 368.12, + 368.14, + 369.01, + 369.02, + 369.03, + 369.04, + 369.05, + 369.06, + 369.07, + 369.08, + 369.09, + 369.1, + 369.11, + 369.12, + 370.01, + 370.02, + 370.03, + 370.04, + 370.05, + 370.06, + 370.07, + 370.08, + 370.09, + 370.1, + 370.11, + 370.12, + 370.14, + 371.01, + 371.02, + 371.03, + 371.04, + 371.05, + 371.06, + 371.07, + 371.08, + 371.09, + 371.1, + 371.11, + 371.12, + 372.01, + 372.02, + 372.03, + 372.04, + 372.05, + 372.06, + 372.07, + 372.08, + 372.09, + 372.1, + 372.11, + 372.12, + 373.01, + 373.02, + 373.03, + 373.04, + 373.05, + 373.06, + 373.07, + 373.08, + 373.09, + 373.1, + 373.11, + 373.12, + 373.14, + 374.01, + 374.02, + 374.03, + 374.04, + 374.05, + 374.06, + 374.07, + 374.08, + 374.09, + 374.1, + 374.11, + 374.12, + 375.01, + 375.02, + 375.03, + 375.04, + 375.05, + 375.06, + 375.07, + 375.08, + 375.09, + 375.1, + 375.11, + 375.12, + 376.01, + 376.02, + 376.03, + 376.04, + 376.05, + 376.06, + 376.07, + 376.08, + 376.09, + 376.1, + 376.11, + 376.12, + 376.14, + 377.01, + 377.02, + 377.03, + 377.04, + 377.05, + 377.06, + 377.07, + 377.08, + 377.09, + 377.1, + 377.11, + 377.12, + 378.01, + 378.02, + 378.03, + 378.04, + 378.05, + 378.06, + 378.07, + 378.08, + 378.09, + 378.1, + 378.11, + 378.12, + 379.01, + 379.02, + 379.03, + 379.04, + 379.05, + 379.06, + 379.13, + 379.07, + 379.08, + 379.09, + 379.1, + 379.11, + 379.12, + 380.01, + 380.02, + 380.03, + 380.04, + 380.05, + 380.06, + 380.07, + 380.08, + 380.09, + 380.1, + 380.11, + 380.12, + 381.01, + 381.02, + 381.03, + 381.04, + 381.05, + 381.06, + 381.07, + 381.08, + 381.09, + 381.1, + 381.11, + 381.12, + 381.14, + 382.01, + 382.02, + 382.03, + 382.04, + 382.05, + 382.06, + 382.07, + 382.08, + 382.09, + 382.1, + 382.11, + 382.12, + 383.01, + 383.02, + 383.03, + 383.04, + 383.05, + 383.06, + 383.07, + 383.08, + 383.09, + 383.1, + 383.11, + 383.12, + 384.01, + 384.02, + 384.03, + 384.04, + 384.05, + 384.06, + 384.07, + 384.08, + 384.09, + 384.1, + 384.11, + 384.12, + 384.14, + 385.01, + 385.02, + 385.03, + 385.04, + 385.05, + 385.06, + 385.07, + 385.08, + 385.09, + 385.1, + 385.11, + 385.12, + 386.01, + 386.02, + 386.03, + 386.04, + 386.05, + 386.06, + 386.07, + 386.08, + 386.09, + 386.1, + 386.11, + 386.12 + ] +} diff --git a/src/fragmentarium/domain/fragment.ts b/src/fragmentarium/domain/fragment.ts index 182c8a7b5..20cd31789 100644 --- a/src/fragmentarium/domain/fragment.ts +++ b/src/fragmentarium/domain/fragment.ts @@ -13,6 +13,7 @@ import { Session } from 'auth/Session' import { ExternalNumbers } from './FragmentDtos' import { RecordEntry } from './RecordEntry' import { ResearchProject } from 'common/researchProject' +import { Date, Dates } from 'fragmentarium/domain/Date' export interface FragmentInfo { readonly number: string @@ -93,7 +94,9 @@ export class Fragment { readonly introduction: Introduction, readonly script: Script, readonly externalNumbers: ExternalNumbers, - readonly projects: ReadonlyArray + readonly projects: ReadonlyArray, + readonly date?: Date, + readonly datesInText?: Dates ) {} static create({ @@ -120,6 +123,8 @@ export class Fragment { script, externalNumbers, projects, + date, + datesInText, }: { number: string accession: string @@ -144,6 +149,8 @@ export class Fragment { script: Script externalNumbers: ExternalNumbers projects: ReadonlyArray + date?: Date + datesInText?: Dates }): Fragment { return new Fragment( number, @@ -168,7 +175,9 @@ export class Fragment { introduction, script, externalNumbers, - projects + projects, + date, + datesInText ) } diff --git a/src/fragmentarium/infrastructure/FragmentRepository.test.ts b/src/fragmentarium/infrastructure/FragmentRepository.test.ts index 7e6887815..bc487c9d2 100644 --- a/src/fragmentarium/infrastructure/FragmentRepository.test.ts +++ b/src/fragmentarium/infrastructure/FragmentRepository.test.ts @@ -76,6 +76,19 @@ const lineToVecRankingDto = { scoreWeighted: [lineToVecScoreDto], } +const date = { + day: { + value: '1', + }, + era: 'Seleucid', + month: { + value: '1', + }, + year: { + value: '1', + }, +} + const fragmentInfo = { number: 'K.1', accession: '1234', @@ -87,6 +100,8 @@ const fragmentInfo = { edition_date: '2019-09-10T13:03:37.575580', references: [], genres: [], + date: date, + dates: [date], } const testData: TestData[] = [ diff --git a/src/fragmentarium/infrastructure/FragmentRepository.ts b/src/fragmentarium/infrastructure/FragmentRepository.ts index d4f345a37..262269cdb 100644 --- a/src/fragmentarium/infrastructure/FragmentRepository.ts +++ b/src/fragmentarium/infrastructure/FragmentRepository.ts @@ -42,6 +42,7 @@ import { PeriodModifiers, Periods } from 'common/period' import { FragmentQuery } from 'query/FragmentQuery' import { QueryItem, QueryResult } from 'query/QueryResult' import { createResearchProject } from 'common/researchProject' +import { Date } from 'fragmentarium/domain/Date' export function createScript(dto: ScriptDto): Script { return { @@ -90,6 +91,10 @@ function createFragment(dto: FragmentDto): Fragment { genres: Genres.fromJson(dto.genres), script: createScript(dto.script), projects: dto.projects.map(createResearchProject), + date: dto.date ? Date.fromJson(dto.date) : undefined, + datesInText: dto.datesInText + ? dto.datesInText.map((date) => Date.fromJson(date)) + : [], }) } diff --git a/src/fragmentarium/ui/info/DateSelection.tsx b/src/fragmentarium/ui/info/DateSelection.tsx new file mode 100644 index 000000000..52d011824 --- /dev/null +++ b/src/fragmentarium/ui/info/DateSelection.tsx @@ -0,0 +1,270 @@ +import React, { ReactNode, useRef, useState } from 'react' +import classNames from 'classnames' +import { Fragment } from 'fragmentarium/domain/fragment' +import { Date as MesopotamianDate } from 'fragmentarium/domain/Date' +import { Session } from 'auth/Session' +import SessionContext from 'auth/SessionContext' +import { Button, Overlay, Popover, InputGroup, Form } from 'react-bootstrap' +import Select from 'react-select' +import BrinkmanKings from 'common/BrinkmanKings.json' +import _ from 'lodash' +import Spinner from 'common/Spinner' +import { Ur3Calendar } from 'fragmentarium/domain/Date' +import { King } from 'common/BrinkmanKings' + +/* +import React, { ReactNode, useEffect } from 'react' +import withData from 'http/withData' +import Select from 'react-select' +import classNames from 'classnames' +import { usePrevious } from 'common/usePrevious' +import withData from 'http/withData' +import { Date } from 'fragmentarium/domain/date' +import _ from 'lodash' +*/ + +type Props = { + fragment: Fragment + //updateDate: (dates: Date[]) => void + //dateOptions: readonly string[][] +} + +export default function DateSelection({ + fragment, +}: //updateDate, +//dateOptions, +Props): JSX.Element { + const [isDisplayed, setIsDisplayed] = useState(false) + const [isKingFieldDisplayed, setIsKingFieldDisplayed] = useState(true) + const [isCalendarFieldDisplayed, setIsCalenderFieldDisplayed] = useState( + false + ) + + const [king, setKing] = useState(undefined) + const [ur3Calendar, setUr3Calendar] = useState( + undefined + ) + + const [year, setYear] = useState('') + const [yearBroken, setYearBroken] = useState(false) + const [yearUncertain, setyearUncertain] = useState(false) + + const [month, setMonth] = useState('') + const [intercalary, setIntercalary] = useState(false) + const [monthBroken, setMonthBroken] = useState(false) + const [monthUncertain, setmonthUncertain] = useState(false) + + const [day, setDay] = useState('') + const [dayBroken, setDayBroken] = useState(false) + const [dayUncertain, setdayUncertain] = useState(false) + + const target = useRef(null) + + /* + useEffect(() => { + if (!_.isEqual(dates, prevDates) && !_.isNil(prevDates)) { + updateDate(dates) + } + }, [dates, prevdates, updateDate]) + */ + + function getInputGroup( + name: string, + setValue: React.Dispatch>, + setBroken: React.Dispatch>, + setUncertain: React.Dispatch> + ): JSX.Element { + return ( + + setValue(event.target.value)} + /> + {name === 'month' && ( + setIntercalary(event.target.checked)} + /> + )} + setBroken(event.target.checked)} + /> + setUncertain(event.target.checked)} + /> + + ) + } + + function getKingInput(): JSX.Element { + const kings = BrinkmanKings.filter( + (king) => !['16', '17'].includes(king.dynastyNumber) + ).map((king) => { + const date = king.date ? ` (${king.date})` : '' + return { + label: `${king.name}${date}, ${king.dynastyName}`, + value: king, + } + }) + return ( + <> + { + setIsKingFieldDisplayed(!event.target.checked) + if (event.target.checked) { + setIsCalenderFieldDisplayed(false) + } + }} + /> + {isKingFieldDisplayed && ( + { + return { label: Ur3Calendar[key], value: key } + })} + onChange={(option): void => { + setUr3Calendar( + Ur3Calendar[option?.value as keyof typeof Ur3Calendar] + ) + }} + isSearchable={true} + autoFocus={true} + placeholder="Calendar" + /> + )} + + ) + } + + const popover = ( + + + {getKingInput()} + {getInputGroup('year', setYear, setYearBroken, setyearUncertain)} + {getInputGroup('month', setMonth, setMonthBroken, setmonthUncertain)} + {getInputGroup('day', setDay, setDayBroken, setdayUncertain)} + + + Saving... + + + + ) + + const session = ( + + {(session: Session): ReactNode => + session.isAllowedToTransliterateFragments() && ( + - - Saving... - + Saving... ) @@ -258,13 +269,16 @@ Props): JSX.Element { /* export default withData< - { fragment: Fragment; updateDates: (dates: Date[]) => void }, + { + fragment: Fragment + updateDate: (date: MesopotamianDate) => Bluebird + }, { fragmentService }, - readonly Date + Date >( - // updateDates={updateDates} - // dateOptions={data} - // updateDates, data - ({ fragment }) => , - (props) => props.fragmentService.fetchdates() -)*/ + ({ fragment, updateDate }) => { + return + }, + (props) => props.fragmentService.fetchDate() +) +*/ diff --git a/src/fragmentarium/ui/info/Details.tsx b/src/fragmentarium/ui/info/Details.tsx index 986a65475..4080a7af5 100644 --- a/src/fragmentarium/ui/info/Details.tsx +++ b/src/fragmentarium/ui/info/Details.tsx @@ -12,6 +12,7 @@ import ScriptSelection from 'fragmentarium/ui/info/ScriptSelection' import DateSelection from 'fragmentarium/ui/info/DateSelection' import FragmentService from 'fragmentarium/application/FragmentService' import Bluebird from 'bluebird' +import { MesopotamianDate } from 'fragmentarium/domain/Date' interface Props { readonly fragment: Fragment @@ -93,10 +94,6 @@ function CdliNumber({ fragment: { cdliNumber } }: Props): JSX.Element { ) } -function Date({ fragment }: Props): JSX.Element { - return -} - function DatesInText({ fragment: { datesInText } }: Props): JSX.Element { return <>Dates in text: } @@ -137,6 +134,7 @@ interface DetailsProps { readonly fragment: Fragment readonly updateGenres: (genres: Genres) => void readonly updateScript: (script: Script) => Bluebird + readonly updateDate: (script: MesopotamianDate) => Bluebird readonly fragmentService: FragmentService } @@ -144,6 +142,7 @@ function Details({ fragment, updateGenres, updateScript, + updateDate, fragmentService, }: DetailsProps): JSX.Element { return ( @@ -184,7 +183,7 @@ function Details({ />
  • - +
  • diff --git a/src/fragmentarium/ui/info/Info.tsx b/src/fragmentarium/ui/info/Info.tsx index 3dd34fc65..536480ef2 100644 --- a/src/fragmentarium/ui/info/Info.tsx +++ b/src/fragmentarium/ui/info/Info.tsx @@ -26,6 +26,7 @@ export default function Info({ onSave(fragmentService.updateGenres(fragment.number, genres)) const updateScript = (script) => fragmentService.updateScript(fragment.number, script) + const updateDate = (date) => fragmentService.updateDate(fragment.number, date) return ( <> @@ -33,6 +34,7 @@ export default function Info({ fragment={fragment} updateGenres={updateGenres} updateScript={updateScript} + updateDate={updateDate} fragmentService={fragmentService} />
    diff --git a/src/test-support/fragment-fixtures.ts b/src/test-support/fragment-fixtures.ts index 0c9e31f27..51bad3be0 100644 --- a/src/test-support/fragment-fixtures.ts +++ b/src/test-support/fragment-fixtures.ts @@ -21,7 +21,7 @@ import { manuscriptFactory } from './manuscript-fixtures' import { Text, createText } from 'corpus/domain/text' import { periodModifiers, periods } from 'common/period' import { ExternalNumbers } from 'fragmentarium/domain/FragmentDtos' -import { Date } from 'fragmentarium/domain/Date' +import { MesopotamianDate } from 'fragmentarium/domain/Date' const defaultChance = new Chance() @@ -218,7 +218,12 @@ export const fragmentFactory = Factory.define( associations.projects ?? [], associations.date ?? - new Date('Seleucid', { value: '1' }, { value: '1' }, { value: '1' }), + new MesopotamianDate( + 'Seleucid', + { value: '1' }, + { value: '1' }, + { value: '1' } + ), associations.datesInText ?? undefined ) } diff --git a/src/test-support/test-fragment.ts b/src/test-support/test-fragment.ts index 448f0d797..9fb99bf7a 100644 --- a/src/test-support/test-fragment.ts +++ b/src/test-support/test-fragment.ts @@ -9,7 +9,7 @@ import Reference from 'bibliography/domain/Reference' import BibliographyEntry from 'bibliography/domain/BibliographyEntry' import FragmentDto from 'fragmentarium/domain/FragmentDtos' import { PeriodModifiers, Periods } from 'common/period' -import { Date as MesopotamianDate } from 'fragmentarium/domain/Date' +import { MesopotamianDate } from 'fragmentarium/domain/Date' const externalNumbers = { cdliNumber: 'A38', From 84c3d60469f7e42e2ac574ee76d1c244ca5e7cd2 Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Tue, 1 Aug 2023 00:24:00 +0000 Subject: [PATCH 04/91] Fix and update tests --- .../ui/info/DateSelection.test.tsx | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/fragmentarium/ui/info/DateSelection.test.tsx b/src/fragmentarium/ui/info/DateSelection.test.tsx index 3213cfda1..de619b7c3 100644 --- a/src/fragmentarium/ui/info/DateSelection.test.tsx +++ b/src/fragmentarium/ui/info/DateSelection.test.tsx @@ -3,21 +3,25 @@ import { render, fireEvent, screen } from '@testing-library/react' import DateSelection from './DateSelection' import { fragment as mockFragment } from 'test-support/test-fragment' import SessionContext from 'auth/SessionContext' +import { Promise } from 'bluebird' let session +let mockUpdateDate beforeEach(() => { session = { isAllowedToTransliterateFragments: jest.fn(), } session.isAllowedToTransliterateFragments.mockReturnValue(true) + mockUpdateDate = jest.fn() + mockUpdateDate.mockReturnValue(Promise.resolve(mockFragment)) }) describe('DateSelection', () => { test('renders without errors', () => { render( - + ) }) @@ -25,7 +29,7 @@ describe('DateSelection', () => { test('displays the date popover when the edit button is clicked', () => { render( - + ) @@ -39,7 +43,7 @@ describe('DateSelection', () => { test('hides the date popover when the Save button is clicked', () => { render( - + ) @@ -54,11 +58,9 @@ describe('DateSelection', () => { }) test('calls the updateDate function with the selected date values when Save is clicked', () => { - const mockUpdateDate = jest.fn() - render( - + ) @@ -78,20 +80,26 @@ describe('DateSelection', () => { fireEvent.click(saveButton) expect(mockUpdateDate).toHaveBeenCalledTimes(1) - expect(mockUpdateDate).toHaveBeenCalledWith([ - { - year: '2022', - month: '3', - day: '15', + expect(mockUpdateDate).toHaveBeenCalledWith({ + day: { broken: false, uncertain: false, value: '15' }, + era: 'seleucid', + month: { broken: false, + intercalary: false, uncertain: false, + value: '3', }, - ]) + ur3Calendar: undefined, + year: { broken: false, uncertain: false, value: '2022' }, + }) }) test('displays the loading spinner when saving', () => { - render() - + render( + + + + ) const editButton = screen.getByLabelText('Browse dates button') fireEvent.click(editButton) @@ -103,7 +111,9 @@ describe('DateSelection', () => { }) test('does not display the edit button for unauthorized users', () => { - render() + render( + + ) const editButton = screen.queryByLabelText('Browse dates button') expect(editButton).not.toBeInTheDocument() From d5d212aa6f98ab75e638eeda361d1ccbc3998c0d Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Tue, 1 Aug 2023 00:41:22 +0000 Subject: [PATCH 05/91] Fix tsc --- src/fragmentarium/application/FragmentService.test.ts | 1 + src/fragmentarium/ui/info/Details.test.tsx | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/fragmentarium/application/FragmentService.test.ts b/src/fragmentarium/application/FragmentService.test.ts index f7ff43dc5..6810d4c9f 100644 --- a/src/fragmentarium/application/FragmentService.test.ts +++ b/src/fragmentarium/application/FragmentService.test.ts @@ -56,6 +56,7 @@ const fragmentRepository = { fetchGenres: jest.fn(), updateGenres: jest.fn(), updateScript: jest.fn(), + updateDate: jest.fn(), fetchPeriods: jest.fn(), updateReferences: jest.fn(), folioPager: jest.fn(), diff --git a/src/fragmentarium/ui/info/Details.test.tsx b/src/fragmentarium/ui/info/Details.test.tsx index 899dbf061..a3fa317d6 100644 --- a/src/fragmentarium/ui/info/Details.test.tsx +++ b/src/fragmentarium/ui/info/Details.test.tsx @@ -27,6 +27,7 @@ const fragmentService = new MockFragmentService() const updateGenres = jest.fn() const updateScript = jest.fn() +const updateDate = jest.fn() let fragment: Fragment @@ -37,6 +38,7 @@ async function renderDetails() { fragment={fragment} updateGenres={updateGenres} updateScript={updateScript} + updateDate={updateDate} fragmentService={fragmentService} /> From 36b15ad9f5bbe93676b415f92a3f759419746104 Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Tue, 1 Aug 2023 16:41:56 +0000 Subject: [PATCH 06/91] Improve & update tests --- src/fragmentarium/domain/Date.ts | 33 ++-- src/fragmentarium/domain/FragmentDtos.ts | 6 +- .../ui/info/DateSelection.test.tsx | 54 +++--- src/fragmentarium/ui/info/DateSelection.tsx | 161 +++++++++++------- src/test-support/test-fragment.ts | 7 +- 5 files changed, 161 insertions(+), 100 deletions(-) diff --git a/src/fragmentarium/domain/Date.ts b/src/fragmentarium/domain/Date.ts index f266a69a8..47ec2beec 100644 --- a/src/fragmentarium/domain/Date.ts +++ b/src/fragmentarium/domain/Date.ts @@ -26,29 +26,39 @@ export enum Ur3Calendar { } export class MesopotamianDate { - era: King | string | undefined year: DateField month: MonthField day: DateField + king?: King + isSeleucidEra?: boolean ur3Calendar?: Ur3Calendar constructor( - era: King | string | undefined, year: DateField, month: MonthField, day: DateField, + king?: King, + isSeleucidEra?: boolean, ur3Calendar?: Ur3Calendar ) { - this.era = era this.year = year this.month = month this.day = day + this.king = king + this.isSeleucidEra = isSeleucidEra this.ur3Calendar = ur3Calendar } static fromJson(dateJSON: MesopotamianDateDto): MesopotamianDate { - const { era, year, month, day } = dateJSON - return new MesopotamianDate(era, year, month, day) + const { year, month, day, king, isSeleucidEra, ur3Calendar } = dateJSON + return new MesopotamianDate( + year, + month, + day, + king, + isSeleucidEra, + ur3Calendar + ) } toString(): string { @@ -59,7 +69,7 @@ export class MesopotamianDate { ] return `${dateParts.join( '.' - )}${this.eraToString()}${this.ur3CalendarToString()}` + )}${this.kingOrEraToString()}${this.ur3CalendarToString()}` } yearToString(): string { @@ -95,14 +105,9 @@ export class MesopotamianDate { }` } - eraToString(): string { - const era = - this.era === 'seleucid' - ? 'SE' - : typeof this.era === 'string' - ? this.era - : this.era?.name ?? '' - return era ? ' ' + era : era + kingOrEraToString(): string { + const eraOrKing = this.isSeleucidEra ? 'SE' : this.king?.name ?? '' + return eraOrKing ? ' ' + eraOrKing : eraOrKing } ur3CalendarToString(): string { diff --git a/src/fragmentarium/domain/FragmentDtos.ts b/src/fragmentarium/domain/FragmentDtos.ts index 569624dd4..4c07f8912 100644 --- a/src/fragmentarium/domain/FragmentDtos.ts +++ b/src/fragmentarium/domain/FragmentDtos.ts @@ -4,6 +4,7 @@ import { Introduction, Notes, ScriptDto } from './fragment' import { RecordEntry } from './RecordEntry' import MuseumNumber from './MuseumNumber' import { King } from 'common/BrinkmanKings' +import { Ur3Calendar } from './Date' interface MeasureDto { value?: number @@ -26,11 +27,12 @@ interface MonthFieldDto extends DateFieldDto { } export interface MesopotamianDateDto { - era: King | string // ToDo: ADD SCHEMA year: DateFieldDto month: MonthFieldDto day: DateFieldDto - ur3Calendar?: string + king?: King + isSeleucidEra?: boolean + ur3Calendar?: Ur3Calendar } export interface TextDto { diff --git a/src/fragmentarium/ui/info/DateSelection.test.tsx b/src/fragmentarium/ui/info/DateSelection.test.tsx index de619b7c3..0036fe718 100644 --- a/src/fragmentarium/ui/info/DateSelection.test.tsx +++ b/src/fragmentarium/ui/info/DateSelection.test.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { render, fireEvent, screen } from '@testing-library/react' +import { render, fireEvent, screen, act } from '@testing-library/react' import DateSelection from './DateSelection' import { fragment as mockFragment } from 'test-support/test-fragment' import SessionContext from 'auth/SessionContext' @@ -34,13 +34,15 @@ describe('DateSelection', () => { ) const editButton = screen.getByLabelText('Browse dates button') - fireEvent.click(editButton) + act(() => { + fireEvent.click(editButton) + }) const popover = screen.getByRole('tooltip') expect(popover).toBeInTheDocument() }) - test('hides the date popover when the Save button is clicked', () => { + test('hides the date popover when the Save button is clicked', async () => { render( @@ -48,64 +50,70 @@ describe('DateSelection', () => { ) const editButton = screen.getByLabelText('Browse dates button') - fireEvent.click(editButton) + act(() => { + fireEvent.click(editButton) + }) const saveButton = screen.getByText('Save') - fireEvent.click(saveButton) + await act(async () => { + fireEvent.click(saveButton) + }) const popover = screen.queryByTestId('popover-select-date') expect(popover).not.toBeInTheDocument() }) - test('calls the updateDate function with the selected date values when Save is clicked', () => { + test('calls the updateDate function with the selected date values when Save is clicked', async () => { render( ) - const editButton = screen.getByLabelText('Browse dates button') - fireEvent.click(editButton) - + act(() => { + fireEvent.click(editButton) + }) const yearInput = screen.getByPlaceholderText('Year') - fireEvent.change(yearInput, { target: { value: '2022' } }) - const monthInput = screen.getByPlaceholderText('Month') - fireEvent.change(monthInput, { target: { value: '3' } }) - const dayInput = screen.getByPlaceholderText('Day') - fireEvent.change(dayInput, { target: { value: '15' } }) - const saveButton = screen.getByText('Save') - fireEvent.click(saveButton) - + await act(async () => { + fireEvent.change(yearInput, { target: { value: '2022' } }) + fireEvent.change(monthInput, { target: { value: '3' } }) + fireEvent.change(dayInput, { target: { value: '15' } }) + }) + await act(async () => { + fireEvent.click(saveButton) + }) expect(mockUpdateDate).toHaveBeenCalledTimes(1) expect(mockUpdateDate).toHaveBeenCalledWith({ day: { broken: false, uncertain: false, value: '15' }, - era: 'seleucid', month: { broken: false, intercalary: false, uncertain: false, value: '3', }, - ur3Calendar: undefined, year: { broken: false, uncertain: false, value: '2022' }, + king: undefined, + isSeleucidEra: true, + ur3Calendar: undefined, }) }) - test('displays the loading spinner when saving', () => { + test('displays the loading spinner when saving', async () => { render( ) const editButton = screen.getByLabelText('Browse dates button') - fireEvent.click(editButton) - + act(() => { + fireEvent.click(editButton) + }) const saveButton = screen.getByText('Save') - fireEvent.click(saveButton) + fireEvent.click(saveButton) const loadingSpinner = screen.getByText('Saving...') expect(loadingSpinner).toBeInTheDocument() }) diff --git a/src/fragmentarium/ui/info/DateSelection.tsx b/src/fragmentarium/ui/info/DateSelection.tsx index 1f2cd6dd3..376058bba 100644 --- a/src/fragmentarium/ui/info/DateSelection.tsx +++ b/src/fragmentarium/ui/info/DateSelection.tsx @@ -25,6 +25,58 @@ type Props = { updateDate: (date: MesopotamianDate) => Bluebird } +type InputGroupProps = { + date: MesopotamianDate | undefined + name: string + setValue: React.Dispatch> + setBroken: React.Dispatch> + setUncertain: React.Dispatch> + setIntercalary: React.Dispatch> +} + +function getInputGroup({ + date, + name, + setValue, + setBroken, + setUncertain, + setIntercalary, +}: InputGroupProps): JSX.Element { + return ( + + setValue(event.target.value)} + value={date ? date[name]?.value : ''} + /> + {name === 'month' && ( + setIntercalary(event.target.checked)} + checked={date?.month?.intercalary} + /> + )} + setBroken(event.target.checked)} + checked={date ? date[name]?.broken : false} + /> + setUncertain(event.target.checked)} + checked={date ? date[name]?.uncertain : false} + /> + + ) +} + export default function DateSelection({ fragment, updateDate, @@ -34,25 +86,37 @@ export default function DateSelection({ const [isSaving, setIsSaving] = useState(false) const [isDisplayed, setIsDisplayed] = useState(false) const [isKingFieldDisplayed, setIsKingFieldDisplayed] = useState( - date?.era !== 'seleucid' + date?.isSeleucidEra ?? false ) const [isCalendarFieldDisplayed, setIsCalenderFieldDisplayed] = useState( false ) - const [king, setKing] = useState(undefined) + const [king, setKing] = useState(fragment.date?.king) const [ur3Calendar, setUr3Calendar] = useState( undefined ) - const [year, setYear] = useState('') - const [yearBroken, setYearBroken] = useState(false) - const [yearUncertain, setyearUncertain] = useState(false) - const [month, setMonth] = useState('') - const [intercalary, setIntercalary] = useState(false) - const [monthBroken, setMonthBroken] = useState(false) - const [monthUncertain, setmonthUncertain] = useState(false) - const [day, setDay] = useState('') - const [dayBroken, setDayBroken] = useState(false) - const [dayUncertain, setdayUncertain] = useState(false) + const [year, setYear] = useState(fragment.date?.year.value ?? '') + const [yearBroken, setYearBroken] = useState( + fragment.date?.year.broken ?? false + ) + const [yearUncertain, setyearUncertain] = useState( + fragment.date?.year.uncertain ?? false + ) + const [month, setMonth] = useState(fragment.date?.month.value ?? '') + const [intercalary, setIntercalary] = useState( + fragment.date?.month.intercalary ?? false + ) + const [monthBroken, setMonthBroken] = useState( + fragment.date?.month.broken ?? false + ) + const [monthUncertain, setMonthUncertain] = useState( + fragment.date?.month.uncertain ?? false + ) + const [day, setDay] = useState(fragment.date?.day.value ?? '') + const [dayBroken, setDayBroken] = useState(fragment.date?.day.broken ?? false) + const [dayUncertain, setDayUncertain] = useState( + fragment.date?.day.uncertain ?? false + ) const target = useRef(null) const kingOptions = getKingOptions() @@ -66,7 +130,6 @@ export default function DateSelection({ function getDate(): MesopotamianDate { return MesopotamianDate.fromJson({ - era: !king && isKingFieldDisplayed ? 'seleucid' : king ?? '', year: { value: year, broken: yearBroken, uncertain: yearUncertain }, month: { value: month, @@ -75,52 +138,13 @@ export default function DateSelection({ uncertain: monthUncertain, }, day: { value: day, broken: dayBroken, uncertain: dayUncertain }, + king: isKingFieldDisplayed && king ? king : undefined, + isSeleucidEra: !king && isKingFieldDisplayed, ur3Calendar: ur3Calendar && isCalendarFieldDisplayed ? ur3Calendar : undefined, }) } - function getInputGroup( - name: string, - setValue: React.Dispatch>, - setBroken: React.Dispatch>, - setUncertain: React.Dispatch> - ): JSX.Element { - return ( - - setValue(event.target.value)} - value={date ? date[name]?.value : ''} - /> - {name === 'month' && ( - setIntercalary(event.target.checked)} - checked={date?.month?.intercalary} - /> - )} - setBroken(event.target.checked)} - checked={date ? date[name]?.broken : false} - /> - setUncertain(event.target.checked)} - checked={date ? date[name]?.uncertain : false} - /> - - ) - } - function getKingSelectLabel(king: King): string { const kingYears = king.date ? ` (${king.date})` : '' return `${king.name}${kingYears}, ${king.dynastyName}` @@ -138,7 +162,7 @@ export default function DateSelection({ } function getCurrentOption(): { label: string; value: King } | undefined { - return kingOptions.find((kingOption) => kingOption.value === date?.era) + return kingOptions.find((kingOption) => kingOption.value === date?.king) } function getKingInput(): JSX.Element { @@ -201,9 +225,30 @@ export default function DateSelection({ > {getKingInput()} - {getInputGroup('year', setYear, setYearBroken, setyearUncertain)} - {getInputGroup('month', setMonth, setMonthBroken, setmonthUncertain)} - {getInputGroup('day', setDay, setDayBroken, setdayUncertain)} + {getInputGroup({ + name: 'year', + date: date, + setValue: setYear, + setBroken: setYearBroken, + setUncertain: setyearUncertain, + setIntercalary: setIntercalary, + })} + {getInputGroup({ + name: 'month', + date: date, + setValue: setMonth, + setBroken: setMonthBroken, + setUncertain: setMonthUncertain, + setIntercalary: setIntercalary, + })} + {getInputGroup({ + name: 'day', + date: date, + setValue: setDay, + setBroken: setDayBroken, + setUncertain: setDayUncertain, + setIntercalary: setIntercalary, + })} + + ) +} + +export default DateForm From 06860d4a518f9375bb5af00f4740fac77160f0d5 Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Mon, 25 Sep 2023 20:00:21 +0000 Subject: [PATCH 37/91] Reorder about tabs --- src/about/ui/about.tsx | 21 ++++++--------------- src/about/ui/chronology.tsx | 2 +- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/about/ui/about.tsx b/src/about/ui/about.tsx index e6f347a29..421fe5fde 100644 --- a/src/about/ui/about.tsx +++ b/src/about/ui/about.tsx @@ -9,7 +9,7 @@ import AboutFragmentarium from 'about/ui/fragmentarium' import AboutCorpus from 'about/ui/corpus' import AboutSigns from 'about/ui/signs' import AboutDictionary from 'about/ui/dictionary' -import AboutChronology from 'about/ui/chronology' +import AboutListOfKings from 'about/ui/chronology' import DateConverterForm from 'chronology/ui/DateConverterForm' export default function About({ @@ -40,20 +40,11 @@ export default function About({ {AboutDictionary(markupService)} - - - - - - - {AboutChronology()} - - + + + + + {AboutListOfKings()} diff --git a/src/about/ui/chronology.tsx b/src/about/ui/chronology.tsx index 1e4cb00b1..3188c78bd 100644 --- a/src/about/ui/chronology.tsx +++ b/src/about/ui/chronology.tsx @@ -2,7 +2,7 @@ import React from 'react' import { Markdown } from 'common/Markdown' import BrinkmanKingsTable from 'chronology/ui/BrinkmanKings' -export default function AboutChronology(): JSX.Element { +export default function AboutListOfKings(): JSX.Element { return ( <> Date: Tue, 26 Sep 2023 15:59:02 +0000 Subject: [PATCH 38/91] Add routes & breadcrumbs to About section --- src/about/ui/about.tsx | 38 +++++++++++++++++++++++++++++++++----- src/router/aboutRoutes.tsx | 24 ++++++++++++++++++------ 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/src/about/ui/about.tsx b/src/about/ui/about.tsx index 421fe5fde..2a5f7bff4 100644 --- a/src/about/ui/about.tsx +++ b/src/about/ui/about.tsx @@ -1,7 +1,8 @@ -import React from 'react' +import React, { useState } from 'react' import { Tabs, Tab } from 'react-bootstrap' +import { useHistory } from 'react-router-dom' import AppContent from 'common/AppContent' -import { SectionCrumb } from 'common/Breadcrumbs' +import { TextCrumb } from 'common/Breadcrumbs' import MarkupService from 'markup/application/MarkupService' import 'about/ui/about.sass' import AboutProject from 'about/ui/project' @@ -11,17 +12,44 @@ import AboutSigns from 'about/ui/signs' import AboutDictionary from 'about/ui/dictionary' import AboutListOfKings from 'about/ui/chronology' import DateConverterForm from 'chronology/ui/DateConverterForm' +import _ from 'lodash' + +export const tabIds = [ + 'project', + 'fragmentarium', + 'corpus', + 'signs', + 'dictionary', + 'date-converter', + 'list-of-kings', +] as const +export type TabId = typeof tabIds[number] export default function About({ markupService, + activeTab, }: { markupService: MarkupService + activeTab: TabId }): JSX.Element { + const history = useHistory() + const [selectedTab, setSelectedTab] = useState(activeTab) + const handleSelect = (selectedTab: TabId) => { + history.push(selectedTab) + setSelectedTab(selectedTab) + } return ( - + handleSelect(selectedTab as TabId)} mountOnEnter unmountOnExit > @@ -43,7 +71,7 @@ export default function About({ - + {AboutListOfKings()} diff --git a/src/router/aboutRoutes.tsx b/src/router/aboutRoutes.tsx index e689abe77..2f6dc66d1 100644 --- a/src/router/aboutRoutes.tsx +++ b/src/router/aboutRoutes.tsx @@ -1,10 +1,14 @@ import React, { ReactNode } from 'react' -import { Route } from 'react-router-dom' -import About from 'about/ui/about' +import { Redirect, Route, RouteComponentProps } from 'react-router-dom' //Redirect +import About, { TabId, tabIds } from 'about/ui/about' import MarkupService from 'markup/application/MarkupService' import { sitemapDefaults } from 'router/sitemap' import { HeadTagsService } from 'router/head' +// ToDo: +// - Update sitemap +// console.log + export default function AboutRoutes({ sitemap, markupService, @@ -14,18 +18,26 @@ export default function AboutRoutes({ }): JSX.Element[] { return [ ( + path={`/about/:id(${tabIds.join('|')})`} + render={(props: RouteComponentProps<{ id: string }>): ReactNode => ( - + )} {...(sitemap && sitemapDefaults)} />, + , ] } From 3be1327fe9a519043e767fedcd856bfb984ca28e Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Sun, 1 Oct 2023 21:52:48 +0000 Subject: [PATCH 39/91] Add routes to About --- .../ui/__snapshots__/about.test.tsx.snap | 1830 +--- src/about/ui/about.test.tsx | 33 +- .../__snapshots__/BrinkmanKings.test.tsx.snap | 9231 ----------------- src/router/aboutRoutes.tsx | 2 + 4 files changed, 483 insertions(+), 10613 deletions(-) delete mode 100644 src/common/__snapshots__/BrinkmanKings.test.tsx.snap diff --git a/src/about/ui/__snapshots__/about.test.tsx.snap b/src/about/ui/__snapshots__/about.test.tsx.snap index 175efd561..b672575d1 100644 --- a/src/about/ui/__snapshots__/about.test.tsx.snap +++ b/src/about/ui/__snapshots__/about.test.tsx.snap @@ -1,1080 +1,345 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Snapshot 1`] = ` - - +
    - - -

    - History of the Project -

    - +
    + +

    + About +

    +
    + +
    +
    +
    + + Ohne feste kritische Grundlage wird das philologische Gebäude auf Sand aufgeführt und die philologische Wissenschaft gestaltet sich zum bloßen Dilettantismus. + +

    + + W. Freund, + + + Triennium philologicum oder Grundzüge der philologischen Wissenschaften + + + . Leipzig, 1874. + +

    +

    - [… who s]aw the Deep, […] the country, + The eBL editions aim to present the best text that can be reconstructed at present. The editions prepared in the course of the project include all previous scholarship on the texts, and in particular all new manuscripts identified after the last printed editions. The eBL edition of the + + + Cuthaean Legend of Narām-Sîn + + + , for instance, almost doubles the manuscript basis of the text available to its last editor; that of the + + + Counsels of Wisdom + + + includes over twenty new manuscripts that were absent from the most recent printed edition. Most of the new manuscripts used have been identified by the eBL team, and are currently being published in the series of articles + + From the Electronic Babylonian Literature Lab + + that appear in the journal + + Kaskal + + . Moreover, the eBL editions are constantly updated, and the editors will incorporate new discoveries as they appear. -
    - + I. Corpus + +

    + + This tablet is a one columned chronicle-fragment, telling about the faulty reignship of king Šulgi, who committed sins against Babylon and Uruk. The text is written in an accusatory tone, stressed by the repetition of exclamatory sentences about Šulgis sinfull deeds. It was discussed in lenghth by + + + , : 63-72 + + (D) + + + + , who pointed out its inspiration trough the Sumerian Kinglist as well as anachronistic allusions to Nabonid. The tablet is part of a series, as can be seen from the existence of the catchline and a “specular catchline” as it is called by Hunger, ( + + + SpTU + + + 1, 20 n. 2), that seems to resume the content of the preceding chapter. About one half or even two thirds of the composition is missing. This is underlined by the colophon, that takes almost all of the space on the reverse but in many other cases covers only about a third and occasionally half of a tablet. The tablet stems from the 27. campaign in Uruk 1969 of the residential area U XVIII and was published first by Hunger 1976 in SpTU 1, 2. + +

    +

    + II. Translations +

    +
    - [who] knew […], […] all […] - -
    + + Foster, Before the Muses + +
    + Foster, + + Before the Muses + +
    +
    +

    + + This tablet is a one columned chronicle-fragment, telling about the faulty reignship of king Šulgi, who committed sins against Babylon and Uruk. The text is written in an accusatory tone, stressed by the repetition of exclamatory sentences about Šulgis sinfull deeds. It was discussed in lenghth by + + + , : 63-72 + + (D) + + + + , who pointed out its inspiration trough the Sumerian Kinglist as well as anachronistic allusions to Nabonid. The tablet is part of a series, as can be seen from the existence of the catchline and a “specular catchline” as it is called by Hunger, ( + + + SpTU + + + 1, 20 n. 2), that seems to resume the content of the preceding chapter. About one half or even two thirds of the composition is missing. This is underlined by the colophon, that takes almost all of the space on the reverse but in many other cases covers only about a third and occasionally half of a tablet. The tablet stems from the 27. campaign in Uruk 1969 of the residential area U XVIII and was published first by Hunger 1976 in SpTU 1, 2. + +

    - [… who] saw the Deep, […] the country, - -
    - - [who] knew […], […] all […] - - - - He who saw the Deep, the foundation of the country, -
    - - who knew the proper ways, was wise in all matters! - -
    - Gilgamesh, who saw the Deep, the foundation of the country, -
    - - who knew the proper ways, was wise in all matters! - -
    - - -

    - List of Participants -

    -
    - The eBL Team in 2020 -
    - The eBL Team in 2020 -
    -
    -

    - Project’s Staff (Cuneiformists) -

    -
      -
    • - Enrique Jiménez, Principal Investigator -
    • -
    • - Zsombor Földi, Editor -
    • -
    • - Aino Hätinen, Editor -
    • -
    • - Adrian Heinrich, Editor (until 03.2022) -
    • -
    • - Tonio Mitto, Editor (PhD student, until 10.2022) -
    • -
    • - Geraldina Rozzi, Editor (since 01.2021) -
    • -
    -

    - Project’s Staff (Developers) -

    -
      -
    • - Ilya Khait (since 03.2022) -
    • -
    • - Jussi Laasonen (until 04.2022) -
    • -
    • - Fabian Simonjetz (since 04.2022) -
    • -
    -
    - The eBL Team in 2023 -
    - The eBL Team in 2023 -
    -
    -

    - Student Assistants -

    -
      -
    • - Yunus Cobanoglu (Computer Science) -
    • -
    • - Cyril Dankwardt -
    • -
    • - Ekaterine Gogokhia -
    • -
    • - Louisa Grill -
    • -
    • - Wasim Khatabe -
    • -
    • - Alexander Kudriavtcev (until 2021) -
    • -
    • - Daniel López-Kuczmik -
    • -
    • - Mays Al-Rawi -
    • -
    • - Wadieh Zerkly -
    • -
    -

    - External Collaborators -

    -
      -
    • - Anmar A. Fadhil (University of Baghdad) -
    • -
    • - Benjamin R. Foster (Yale University) -
    • -
    • - Alberto Giannese (British Museum) -
    • -
    • - Carmen Gütschow -
    • -
    • - Ivor Kerslake (British Museum) -
    • -
    • - Felix Müller (Universität Göttingen) -
    • -
    • - Jeremiah Peterson -
    • -
    • - Luis Sáenz (Universität Heidelberg) -
    • -
    • - Henry Stadhouders -
    • -
    • - Junko Taniguchi -
    • -
    • - Abraham Winitzer (University of Notre Dame) -
    • -
    -

    - Participating Institutions -

    - - - - - - -

    - - -

    - I. How to Cite -

    - -

    - - - - - 1/1/2023 - - - -

    - - Creative Commons License - -

    -

    - II. Sources of the Catalogue -

    - -

    - -

    - -

    - III. Photographs -

    - The photographs of tablets from The British Museum’s Kuyunjik collection were produced in 2009-2013, as part of the on-going “Ashurbanipal Library Project” (2002–present), thanks to funding provided by The Townley Group and The Andrew Mellon Foundation. The photographs were produced by Marieka Arksey, Kristin A. Phelps, Sarah Readings, and Ana Tam; with the assistance of Alberto Giannese, Gina Konstantopoulos, Chiara Salvador, and Mathilde Touillon-Ricci. They are displayed on the eBL website courtesy of Dr. Jon Taylor, director of the “Ashurbanipal Library Project.” -

    -

    - I. Kerslake in the British Museum -
    - I. Kerslake photographs tablets in the British Museum, 2019 -
    -
    - The photographs of the The British Museum’s Babylon collection are taken by Alberto Giannese and Ivor Kerslake (2019–present) in the framework of the “electronic Babylonian Literature” project, funded by a Sofia Kovalevskaja Award (Alexander von Humboldt Stiftung). -

    - The photographs of the tablets in the Iraq Museum have been produced by Anmar A. Fadhil (University of Baghdad – eBL Project), and displayed by permission of the State Board of Antiquities and Heritage and The Iraq Museum. -

    - The photographs of the tablets in the Yale Babylonian Collection are being produced by Klaus Wagensonner (Yale University), and used with the kind permission of the Agnete W. Lassen (Associate Curator of the Yale Babylonian Collection, Yale Peabody Museum). -

    - The images cannot be reproduced without the explicit consent of the funding projects and institutions, as well as the institutions in which the cuneiform tablets are kept. Users are referred to the conditions for reproducing the images in the links shown in the captions under the images. -

    -

    - IV. Editions in the Fragmentarium -

    -
    - List of fragments to revise -
    - List of texts to revise, eBL team -
    -
    - The editions in the Fragmentarium have been produced by the entire eBL Team, starting in 2018. Thousands of them were produced on the basis of photographs and have not been collated in the museum. Although the speed at which fragments have been transliterated has been necessarily fast, the quality control measurements adopted, and in particular the policy to have each edition revised by a scholar different from the original editor, means that they are normally reliable. Each member of the team has produced some 40 editions and revised some 60 editions a month on average. -

    - In addition, the - - - BabMed team - - - has kindly made acessible its large collections of transliterations of Mesopotamian medicine for their use on the Fragmentarium. They have been imported by the eBL team using the importer developed by T. Englmeier (see - - - here - - - and - - - here - - ), and thoroughly revised and lemmatized chiefly by H. Stadhouders. The transliterations of the BabMed team were originally produced by Markham J. Geller, J. Cale Johnson, Ulrike Steinert, Stravil V. Panayotov, Eric Schmidtchen, Krisztián Simkó, Marius Hoppe, Marie Lorenz, John Schlesinger, Till Kappus, and Agnes Kloocke (at FU Berlin), as well as Annie Attia, Sona Eypper, and Henry Stadhouders (as external collaborators). -

    -

    - V. Folios -

    - The electronic Babylonian Literature (eBL) project, and in particular its Fragmentarium, continues the efforts of generations of Assyriologists to rescue the literature of Ancient Mesopotamia from the hands of oblivion. The Fragmentarium stands on the shoulders of previous scholars, and has used extensively their unpublished, unfinished work, for compiling its database of transliterations. It is a pleasure to acknowledge our gratitude to the following scholars: -

    - V.1. George Smith (26 March 1840 – 19 August 1876) -

    - -
    - G. Smith’s draft copy of DT.1 -
    - G. Smith’s draft copy of DT.1 -
    -
    - -

    - V.2. Johann Strassmaier, S.J. (15 May 1846 – 11 January 1920) -

    -
    - Johann Strassmaier, S.J. (courtesy of W. R. Mayer) -
    - Johann Strassmaier, S.J. (courtesy of W. R. Mayer) -
    -
    - -
    - Collection of Strassmaier’s copies at the Pontifical Biblical Institute -
    - Collection of Strassmaier’s copies at the Pontifical Biblical Institute -
    -
    - -

    - V.3. Carl Bezold (18 May 1859 – 21 November 1922) -

    -
    - Carte de visite of Bezold at the British Museum (courtesy J. Taylor) -
    - Carte de visite of Bezold at the British Museum (courtesy J. Taylor) -
    -
    - -

    - -

    - V.4. Friedrich W. Geers (24 January 1885 – 29 January 1955) -

    -
    - Collection of Geers’s copies once at the Oriental Institute -
    - Collection of Geers’s copies once at the Oriental Institute -
    -
    - -

    - -

    - V.5. Erica Reiner (4 August 1924 – 31 December 2005) -

    -
    - Notebooks by E. Reiner -
    - Notebooks by E. Reiner -
    -
    - -

    - -

    - V.6. W. G. Lambert (26 February 1926 – 9 November 2011) -

    - -
    - W. G. Lambert in Wassenaar, 1990 (courtesy U. Kasten) -
    - W. G. Lambert in Wassenaar, 1990 (courtesy U. Kasten) -
    -
    - - -

    - V.7. Riekele Borger (24 May 1929 – 27 December 2010) -

    -
    - R. Borger and W. G. Lambert in the British Museum (courtesy J. Taylor) -
    - R. Borger and W. G. Lambert in the British Museum (courtesy J. Taylor) -
    -
    - - -

    - V.8. Aaron Shaffer (2 January 1933 – 5 April 2004) -

    -
    - Aaron Shaffer in Chicago (courtesy N. Wasserman) -
    - Aaron Shaffer working in Chicago (courtesy N. Wasserman) -
    -
    - - -

    -

    - V.9. Erle Leichty (7 August 1933 – 19 September 2016) -

    - -

    - -

    - E. Leichty’s note on notebook NB 911 -
    - E. Leichty’s note on notebook NB 911 -
    -
    - -

    - - -

    - V.10. Stephen J. Lieberman (1943 – 1992) -

    - -

    - -

    - V.11. A. Kirk Grayson -

    - -

    - V.12. Werner R. Mayer, S.J. -

    -
    - Transliteration by W. R. Mayer -
    - Transliteration by W. R. Mayer -
    -
    - -

    - V.13. Markham J. Geller -

    - -

    - V.14. Simo Parpola -

    -
    - Parpola’s transliteration and identification of Rm.468 -
    - Parpola’s transliteration and identification of - + and - Rm.468 + Hymn to Ninurta as Savior -
    -
    - -

    - V.15. Irving L. Finkel -

    -
    - List of “joins” in a notebook by I. L. Finkel -
    - List of “joins” in a notebook by I. L. Finkel -
    -
    - -

    - V.16. Andrew R. George -

    -
    - Transliteration by A. R. George -
    - Transliteration by A. R. George -
    -
    - -

    - V.17. Ulla Koch -

    - -

    - V.18. Jeremiah L. Peterson -

    - -

    - V.19. Uri Gabbay -

    - -
    -
    - - -
    - - Ohne feste kritische Grundlage wird das philologische Gebäude auf Sand aufgeführt und die philologische Wissenschaft gestaltet sich zum bloßen Dilettantismus. - + ) and E. Jiménez. +

    - -

    -

    - - -

    - I. Corpus -

    - -

    - II. Translations -

    -
    - + In addition, a series of translations into Arabic are in preparation by A. A. Fadhil, W. Khatabe, and W. Zerkly (see for now A. A. Fadhil’s Arabic translation of + + + Enūma eliš + + I + + ) + +

    + III. Ideal Text +

    + + The main version displayed on the eBL Corpus is a phonetic transcription of the text, which has been adjusted according to the rules of Standard Babylonian grammar. This practice somewhat departs from the Assyriological tradition of editing “eclectic” texts, i.e. transliterations that combine the readings of various manuscripts. It has been adopted, however, in the conviction that Mesopotamian texts are also objects of art, and not just objects of scientific study, and as such convey their message only through the interplay of form and content. + +
    Foster, Before the Muses - -
    - Foster, - - Before the Muses - -
    -
    - - -

    - -

    - III. Ideal Text -

    - -
    - eBL edition of Enūma eliš I 49 -
    - eBL edition of +
    + eBL edition of + + Enūma eliš + + + + I 49 + +
    +
    +

    + + The practice of using a phonetic transcription as the main text no doubt has disadvantages: for instance, it obscures the way in which the text is written in cuneiform, and it affords a sense of grammatical certainty that is absent from a regular transliteration. However, it also offers considerable advantages: in particular, it does not require the editor to adopt any particular spelling when no good criteria exist for preferring one over the other. In Enūma eliš @@ -1084,341 +349,158 @@ exports[`Snapshot 1`] = ` > I 49 - -

    -

    - -

    - -

    - IV. Score Edition -

    -
    - eBL edition of Šamaš Hymn 134 -
    - eBL edition of + (see the adjoining image), for instance, the editor would have to choose between the accusative + + al-ka-ta + + , attested only in Assyrian manuscripts, or the normal Babylonian spelling + + al-ka-tu + + ₄. In a transcription the editor can convey his interpretation of the text in a much more satisfactory manner than in a traditional transliteration. + +

    + + The transcription respects the ways in which the manuscripts are written as much as possible. For instance, - Šamaš Hymn + Enūma eliš - 134 + VI 124 -

    -
    - -

    - -

    - V. Paratextual information -

    - -

    - -

    - -

    - VI. Šumma ālu -

    - -
    - - Université de Genève - - - Fonds national suisse de la recherche scientifique - -
    -
    -
    - - - -

    -

    - I. Sign information -

    - -

    - -

    - -

    - II. Mesopotamisches Zeichenlexikon -

    -
    - - Borger, Mesopotamisches Zeichenlexikon - -
    - Borger, + is transcribed as - Mesopotamisches Zeichenlexikon + muṭaḫḫidu urîšun -
    -
    - -

    - - - - different color - - -

    - -

    - -

    - III. Fossey, Manuel d’assyriologie II -

    -
    - Fossey, Manuel d’assyriologie II -
    - Fossey, + , “who enriches their stables,” and thus assumes a hymno-epic ending - - Manuel d’assyriologie II + u -
    -
    - -

    - -

    - IV. Palaeography -

    - -

    - - - - - - -

    - I. A Concise Dictionary of Akkadian -

    -
    - + nomen regens + + , instead of the normal bound form + + muṭaḫḫid + + , since + + mu-ṭaḫ-ḫi-du + + is the spelling of all manuscripts. + +

    + IV. Score Edition +

    +
    Black, George, Postgate, A Concise Dictionary of Akkadian - -
    - Black, George, Postgate, +
    + eBL edition of + + Šamaš Hymn + + + + 134 + +
    +
    + + Since the number of manuscripts of each text is constantly growing, cuneiform studies is reaching the point where it is no longer possible to print text editions in the score format. Just the eBL edition score of - A Concise Dictionary of Akkadian + Enūma eliš - -
    - -

    - -

    -

    - II. Akkadian-Arabic Reference Dictionary -

    - - -

    - III. Akkadische Logogramme -

    - -

    - IV. Akkadische Glossare und Indizes (AfO Register) -

    - -

    - -

    - V. Supplement to the Akkadian Dictionaries -

    - -
    -
    - - - - - - - - + , for example, would require some 300 pages in font size 10. Despite this technical limitation, scores are the fastest, most straightforward way of checking exactly how manuscripts write their texts. The eBL scores are, moreover, aligned with the ideal line, so that the reader can check the manuscript basis of the editor’s decisions at any time. + +

    + + All transliterations have been checked twice against the published copies and against photographs and in some cases the originals of the cuneiform tablets. + +

    + V. Paratextual information +

    + + Each text is furnished with an introduction, which discusses the content and structure of the text, its origins and transmission, its Sitz im Leben and the history of research concerning the text. + +

    + + The editions are fully lemmatized and annotated. The annotation includes indications of all parallel lines, so that the text can be studied as part of the intertextual network in which it belongs. In addition, the notes on individual lines endeavor to provide the reader with references to all previous bibliography, with particular emphasis on studies which have appeared in the last few years. The notes on the score edition discuss mostly philological issues pertaining to an individual manuscript. + +

    + + The colophons of the individual manuscripts are transliterated independently, and can be accessed on the homepage of any text (e.g. + + here + + ). In some cases, manuscripts include lines that, though clearly part of the composition in question, cannot yet be placed in it, and thus are transliterated independently, as Unplaced lines. + +

    + VI. Šumma ālu +

    + + The editions of + + Šumma ālu + + presented here were prepared in the context of the projects “Edition of the Omen Series Šumma Alu” (2017–2021; + + http://p3.snf.ch/project-175970 + + ) and “Typology and potential of the excerpt tablets of Šumma alu” (2022–2023; + + http://p3.snf.ch/project-205122 + + ), both directed by Prof. Catherine Mittermayer at the University of Geneva and funded by the Swiss National Science Foundation. The complete score editions can be downloaded (PDF) at the “Archive ouverte” of the University of Geneva ( + + https://archive-ouverte.unige.ch/ + + ; search for “Shumma alu”). + +
    + + Université de Genève + + + Fonds national suisse de la recherche scientifique + +
    +
    +
    + +
    + `; diff --git a/src/about/ui/about.test.tsx b/src/about/ui/about.test.tsx index 76897ab9b..266c06866 100644 --- a/src/about/ui/about.test.tsx +++ b/src/about/ui/about.test.tsx @@ -1,7 +1,12 @@ +import React from 'react' import About from 'about/ui/about' import Bluebird from 'bluebird' +import '@testing-library/jest-dom/extend-expect' import MarkupService from 'markup/application/MarkupService' import { markupDtoSerialized } from 'test-support/markup-fixtures' +import { act, render, screen, waitFor } from '@testing-library/react' +import { MemoryRouter } from 'react-router-dom' +import { waitForSpinnerToBeRemoved } from 'test-support/waitForSpinnerToBeRemoved' jest.mock('markup/application/MarkupService') @@ -15,14 +20,26 @@ afterAll(() => { mockDate.mockRestore() }) -const MockMarkupService = MarkupService as jest.Mock> -const markupServiceMock = new MockMarkupService() +const markupServiceMock = new (MarkupService as jest.Mock< + jest.Mocked +>)() -markupServiceMock.fromString.mockReturnValue( - Bluebird.resolve(markupDtoSerialized) -) - -test('Snapshot', () => { +test('Snapshot', async () => { mockDate.mockReturnValue('1/1/2023') - expect(About({ markupService: markupServiceMock })).toMatchSnapshot() + markupServiceMock.fromString.mockReturnValue( + Bluebird.resolve(markupDtoSerialized) + ) + + await act(async () => { + const { container } = await render( + + + + ) + await waitForSpinnerToBeRemoved(screen) + await waitFor(() => { + expect(screen.queryByText('Loading...')).not.toBeInTheDocument() + }) + expect(container).toMatchSnapshot() + }) }) diff --git a/src/common/__snapshots__/BrinkmanKings.test.tsx.snap b/src/common/__snapshots__/BrinkmanKings.test.tsx.snap deleted file mode 100644 index 242dcea5c..000000000 --- a/src/common/__snapshots__/BrinkmanKings.test.tsx.snap +++ /dev/null @@ -1,9231 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Snapshot 1`] = ` - - - - - -

    - 1. Dynasty of Akkad -

    - - - - - 1 - - - Sargon - - - 2334–2279 - - (56?) - - - - - - - 2 - - - Rimuš - - - 2278–2270 - - (9?) - - - - - - - 3 - - - Maništušu - - - 2269–2255 - - (15?) - - - - - - - 4 - - - Naram-Sin - - - 2254–2218 - - (37?) - - - - - - - 5 - - - Šar-kali-šarri - - - 2217–2193 - - (25) - - - - - - - 6 - - - Igigi - - - 2192–2190 - - (3) - - - - - - - 7 - - - Naniyum - - - - - 8 - - - Imi - - - - - 9 - - - Elulu - - - - - 10 - - - Dudu - - - 2189–2169 - - (21) - - - - - - - 11 - - - Šu-Durul - - - 2168–2154 - - (15) - - - - -
    - - - -

    - 2. Third Dynasty of Ur -

    - - - - - 1 - - - Ur-Namma - - - 2110–2093 - - (18) - - - - - - - 2 - - - Šulgi - - - 2092–2045 - - (48) - - - - - - - 3 - - - Amar-Suen - - - 2044–2036 - - (9) - - - - - - - 4 - - - Šu-Sin - - - 2035–2027 - - (9) - - - - - - - 5 - - - Ibbi-Sin - - - 2026–2003 - - (24) - - - - -
    - - - -

    - 3. First Dynasty of Isin -

    - - - - - 1 - - - Išbi-Erra - - - 2019–1987 - - (33) - - - - - - - 2 - - - Šu-ilišu - - - 1986–1977 - - (10) - - - - - - - 3 - - - Iddin-Dagan - - - 1976–1956 - - (21) - - - - - - - 4 - - - Išme-Dagan - - - 1955–1937 - - (19) - - - - - - - 5 - - - Lipit-Eštar - - - 1936–1926 - - (11) - - - - - - - 6 - - - Ur-Ninurta - - - 1925–1898 - - (28) - - - - - - - 7 - - - Bur-Sin - - - 1897–1876 - - (22) - - - - - - - 8 - - - Lipit-Enlil - - - 1875–1871 - - (5) - - - - - - - 9 - - - Erra-imitti - - - 1870–1863 - - (8) - - - - - - - 10 - - - Enlil-bani - - - 1862–1839 - - (24) - - - - - - - 11 - - - Zambiya - - - 1838–1836 - - (3) - - - - - - - 12 - - - Iter-piša - - - 1835–1832 - - (4) - - - - - - - 13 - - - Urdukuga - - - 1831–1828 - - (4) - - - - - - - 14 - - - Sin-magir - - - 1827–1817 - - (11) - - - - - - - 15 - - - Damiq-ilišu - - - 1816–1794 - - (23) - - - - -
    - - - -

    - 4. Larsa Dynasty -

    - - - - - 1 - - - Naplanum - - - 2025–2005 - - (21) - - - - - - - 2 - - - Emiṣum - - - 2004–1977 - - (28) - - - - - - - 3 - - - Samium - - - 1976–1942 - - (35) - - - - - - - 4 - - - Zabaya - - - 1941–1933 - - (9) - - - - - - - 5 - - - Gungunum - - - 1932–1906 - - (27) - - - - - - - 6 - - - Abisare - - - 1905–1895 - - (11) - - - - - - - 7 - - - Sumuel - - - 1894–1866 - - (29) - - - - - - - 8 - - - Nur-Adad - - - 1865–1850 - - (16) - - - - - - - 9 - - - Sin-iddinam - - - 1849–1843 - - (7) - - - - - - - 10 - - - Sin-iribam - - - 1842–1841 - - (2) - - - - - - - 11 - - - Sin-iqišam - - - 1840–1836 - - (5) - - - - - - - 12 - - - Ṣilli-Adad - - - 1835 - - - - - - - - - 13 - - - Warad-Sin - - - 1834–1823 - - (12) - - - - - - - 14 - - - Rim-Sin I - - - 1822–1763 - - (60) - - - - -
    - - - -

    - 5. First Dynasty of Babylon (Hammurapi Dynasty) -

    - - - - - 1 - - - Sumuabum - - - 1894–1881 - - (14) - - - - - - - 2 - - - Sumulael - - - 1880–1845 - - (36) - - - - - - - 3 - - - Sabium - - - 1844–1831 - - (14) - - - - - - - 4 - - - Apil-Sin - - - 1830–1813 - - (18) - - - - - - - 5 - - - Sin-muballiṭ - - - 1812–1793 - - (20) - - - - - - - 6 - - - Hammurapi - - - 1792–1750 - - (43) - - - - - - - 7 - - - Samsuiluna - - - 1749–1712 - - (38) - - - - - - - 8 - - - Abi-ešuh - - - 1711–1684 - - (28) - - - - - - - 9 - - - Ammiditana - - - 1683–1647 - - (37) - - - - - - - 10 - - - Ammiṣaduqa - - - 1646–1626 - - (21) - - - - - - - 11 - - - Samsuditana - - - 1625–1595 - - (31) - - - - -
    - - - -

    - 6. First Dynasty of the Sealand -

    - - - - - 1 - - - Ilima-ilum - - - - - - - - - - - - 2 - - - Itti-ili-nibi - - - - - - - - - - - - 3 - - - Damqi-ilišu - - - - - - - - - - - - 4 - - - Iškibal - - - - - (15) - - - - - - - 5 - - - Šušši - - - - - (24) - - - - - - - 6 - - - Gulkišar - - - - - (55) - - - - - - - 6a - - - ᴵDIŠ+U-EN - - - - - - - - - - - - 7 - - - Pešgaldarameš - - - - - (50) - - - - - - - 8 - - - Ayadarakalama - - - - - (28) - - - - - - - 9 - - - Akurduana - - - - - (26) - - - - - - - 10 - - - Melamkurkura - - - - - (7) - - - - - - - 11 - - - Ea-gamil - - - - - (9) - - - - -
    - - - -

    - 7. Kassite Dynasty -

    - - - - - 1 - - - Gandaš - - - - - (26) - - - - - - - 2 - - - Agum I - - - - - (22) - - - - - - - 3 - - - Kaštiliašu I - - - - - (22) - - - - - - - 4–5 - - - (uncertain) - - - - - - - - - - - - 6 - - - Urzigurumaš - - - - - - - - - - - - 7 - - - Harba-x - - - - - - - - - - - - - - - (…) - - - - - - - - - - - - - - - Agum II - - - - - - - - - - - - - - - (…) - - - - - - - - - - - - 10 - - - Burna-Buriaš I - - - - - - - - - - - - - - - (…) - - - - - - - - - - - - - - - Kaštiliašu III - - - - - - - - - - - - - - - (…) - - - - - - - - - - - - - - - Agum III - - - - - - - - - - - - - - - (…) - - - - - - - - - - - - 15 - - - Karaindaš - - - - - - - - - - - - 16 - - - Kadašman-Harbe I - - - - - - - - - - - - 17 - - - Kurigalzu I - - - - - - - - - - - - 18 - - - Kadašman-Enlil I - - - (1373)-1359 - - (15) - - - - - - - 19 - - - Burna-Buriaš II - - - 1358–1331 - - (28) - - - - - - - 20 - - - Kara-hardaš - - - 1331 - - - - - - - - - 21 - - - Nazi-Bugaš - - - 1331 - - - - - - - - - 22 - - - Kurigalzu II - - - 1330–1306 - - (25) - - - - - - - 23 - - - Nazi-Maruttaš - - - 1305–1280 - - (26) - - - - - - - 24 - - - Kadašman-Turgu - - - 1279–1262 - - (18) - - - - - - - 25 - - - Kadašman-Enlil II - - - 1261–1253 - - (9) - - - - - - - 26 - - - Kudur-Enlil - - - 1252–1244 - - (9) - - - - - - - 27 - - - Šagarakti-Šuriaš - - - 1243–1231 - - (13) - - - - - - - 28 - - - Kaštiliašu (IV) - - - 1230–1223 - - (8) - - - - - - - 28a - - - Tukulti-Ninurta (I) - - - 1223? - - - - - - - - - 29 - - - Enlil-nadin-šumi - - - 1222 - - (1) - - - - - - - 30 - - - Kadašman-Harbe II - - - 1221 - - (1) - - - - - - - 31 - - - Adad-šuma-iddina - - - 1220–1215 - - (6) - - - - - - - 32 - - - Adad-šuma-uṣur - - - 1214–1185 - - (30) - - - - - - - 33 - - - Meli-Šipak - - - 1184–1170 - - (15) - - - - - - - 34 - - - Marduk-apla-iddina I - - - 1169–1157 - - (13) - - - - - - - 35 - - - Zababa-šuma-iddina - - - 1156 - - (1) - - - - - - - 36 - - - Enlil-nadin-ahi - - - 1155–1153 - - (3) - - - - -
    - - - -

    - 8. Second Dynasty of Isin -

    - - - - - 1 - - - Marduk-kabit-ahhešu - - - 1157–1140 - - (18) - - - - - - - 2 - - - Itti-Marduk-balaṭu - - - 1139–1132 - - (8) - - - - - - - 3 - - - Ninurta-nadin-šumi - - - 1131–1126 - - (6) - - - - - - - 4 - - - Nebuchadnezzar I - - - 1125–1104 - - (22) - - - - - - - 5 - - - Enlil-nadin-apli - - - 1103–1100 - - (4) - - - - - - - 6 - - - Marduk-nadin-ahhe - - - 1099–1082 - - (18) - - - - - - - 7 - - - Marduk-šapik-zeri - - - 1081–1069 - - (13) - - - - - - - 8 - - - Adad-apla-iddina - - - 1068–1047 - - (22) - - - - - - - 9 - - - Marduk-ahhe-eriba - - - 1046 - - (1) - - - - - - - 10 - - - Marduk-zer-x - - - 1045–1034 - - (12) - - - - - - - 11 - - - Nabu-šumu-libur - - - 1033–1026 - - (8) - - - - -
    - - - -

    - 9. Second Dynasty of the Sealand -

    - - - - - 1 - - - Simbar-Šipak - - - 1025–1008 - - (18) - - - - - - - 2 - - - Ea-mukin-zeri - - - 1008 - - (5 months) - - - - - - - 3 - - - Kaššu-nadin-ahhe - - - 1007–1005 - - (3) - - - - -
    - - - -

    - 10. Bazi Dynasty -

    - - - - - 1 - - - Eulmaš-šakin-šumi - - - 1004–988 - - (17) - - - - - - - 2 - - - Ninurta-kudurri-uṣur I - - - 987–985 - - (3) - - - - - - - 3 - - - Širikti-Šuqamuna - - - 985 - - (3 months) - - - - -
    - - - -

    - 11. Elamite Dynasty -

    - - - - - 1 - - - Mar-biti-apla-uṣur - - - 984–979 - - (6) - - - - -
    - - - -

    - 12. Miscellaneous Dynasties -

    - - - - - 1 - - - Nabu-mukin-apli - - - 978–943 - - (36) - - - - - - - 2 - - - Ninurta-kudurri-uṣur II - - - 943 - - (8 months) - - - - - - - 3 - - - Mar-biti-ahhe-iddina - - - 942-? - - - - - - - - - 4 - - - Šamaš-mudammiq - - - ?-c. 900 - - - - - - - - - 5 - - - Nabu-šuma-ukin I - - - c. 899-c. 888 - - - - - - - - - 6 - - - Nabu-apla-iddina - - - c. 887–851 - - - - - - - - - 7 - - - Marduk-zakir-šumi I - - - 850-c. 819 - - - - - - - - - 8 - - - Marduk-balassu-iqbi - - - c. 818-c. 813 - - - - - - - - - 9 - - - Baba-aha-iddina - - - c. 812 - - - - - - - - - - - - (interregnum) - - - - - - - - - - - - 10 - - - Ninurta-apl?-[x] - - - - - - - - - - - - 11 - - - Marduk-bel-zeri - - - - - - - - - - - - 12 - - - Marduk-apla-uṣur - - - - - - - - - - - - 13 - - - Eriba-Marduk - - - - - - - - - - - - 14 - - - Nabu-šuma-iškun - - - (760)-748 - - (13) - - - - - - - 15 - - - Nabu-naṣir - - - 747–734 - - (14) - - - - - - - 16 - - - Nabu-nadin-zeri - - - 733–732 - - (2) - - - - - - - 17 - - - Nabu-šuma-ukin II - - - 732 - - (1 month) - - - - - - - 18 - - - Nabu-mukin-zeri - - - 731–729 - - (3) - - - - - - - 19 - - - Tiglath-pileser / Pulu - - - 728–727 - - (2) - - - - - - - 20 - - - Shalmaneser / Ululayu - - - 726–722 - - (5) - - - - - - - 21 - - - Merodach-Baladan (II) - - - 721–710 - - (12) - - - - - - - 22 - - - Sargon II - - - 709–705 - - (5) - - - - - - - 23 - - - Sennacherib - - - 704–703 - - (2) - - - - - - - 24 - - - Marduk-zakir-šumi II - - - 703 - - (1 month) - - - - - - - 25 - - - Merodach-Baladan (II) - - - 703 - - (9 months) - - - - - - - 26 - - - Bel-ibni - - - 702–700 - - (3) - - - - - - - 27 - - - Aššur-nadin-šumi - - - 699–694 - - (6) - - - - - - - 28 - - - Nergal-ušezib - - - 693 - - (1) - - - - - - - 29 - - - Mušezib-Marduk - - - 692–689 - - (4) - - - - - - - 30 - - - Sennacherib - - - 688–681 - - (8) - - - - - - - 31 - - - Esarhaddon - - - 680–669 - - (12) - - - - - - - 31a - - - Ashurbanipal - - - 668 - - (1) - - - - - - - 32 - - - Šamaš-šum-ukin - - - 667–648 - - (20) - - - - - - - 33 - - - Kandalanu - - - 647–627 - - (21) - - - - - - - - - - (interregnum) - - - 626 - - (1) - - - - -
    - - - -

    - 13. Neo-Babylonian Dynasty -

    - - - - - 1 - - - Nabopolassar - - - 625–605 - - (21) - - - - - - - 2 - - - Nebuchadnezzar II - - - 604–562 - - (43) - - - - - - - 3 - - - Evil-Merodach - - - 561–560 - - (2) - - - - - - - 4 - - - Neriglissar - - - 559–556 - - (4) - - - - - - - 5 - - - Labaši-Marduk - - - 556 - - (3 months) - - - - - - - 6 - - - Nabonidus - - - 555–539 - - (17) - - - - -
    - - - -

    - 14. Persian Rulers -

    - - - - - 1 - - - Cyrus - - - 538–530 - - (9) - - - - - - - 2 - - - Cambyses - - - 529–522 - - (8) - - - - - - - 2a - - - Bardiya - - - 522 - - - - - - - - - 2b - - - Nebuchadnezzar III - - - 522 - - - - - - - - - 2c - - - Nebuchadnezzar IV - - - 521 - - - - - - - - - 3 - - - Darius I - - - 521–486 - - (36) - - - - - - - 4 - - - Xerxes (I) - - - 485–465 - - (21) - - - - - - - 4a - - - Bel-šimanni - - - 484 - - - - - - - - - 4b - - - Šamaš-eriba - - - 484 - - - - - - - - - 5 - - - Artaxerxes I - - - 464–424 - - (41) - - - - - - - 6 - - - Darius II - - - 423–405 - - (19) - - - - - - - 7 - - - Artaxerxes II Mnemon - - - 404–359 - - (46) - - - - - - - 8 - - - Artaxerxes III Ochus - - - 358–338 - - (21) - - - - - - - 9 - - - Artaxerxes IV Arses - - - 337–336 - - (2) - - - - - - - 10 - - - Darius III - - - 335–331 - - (5) - - - - -
    - - - -

    - 15. Macedonian Rulers -

    - - - - - 1 - - - Alexander (III) - - - 330–323 - - - - - - - - - 2 - - - Philip Arrhidaeus - - - 323–316 - - - - - - - - - 3 - - - Antigonus - - - 315–311 - - - - - - - - - 4 - - - Alexander (IV) - - - 311–306 - - - - - - -
    - - - -

    - 16. Seleucid Rulers -

    - - - - - 1 - - - Seleucus I Nicator - - - 305–281 - - - - - - - - - 2 - - - Antiochus I Soter - - - 281–261 - - - - - - - - - 3 - - - Antiochus II Theos - - - 261–246 - - - - - - - - - 4 - - - Seleucus II Callinicus - - - 246–225 - - - - - - - - - 5 - - - Seleucus III Soter - - - 225–223 - - - - - - - - - 6 - - - Antiochus III (the Great) - - - 222–187 - - - - - - - - - 7 - - - Seleucus IV Philopator - - - 187–175 - - - - - - - - - 8 - - - Antiochus IV Epiphanes - - - 175–164 - - - - - - - - - 9 - - - Antiochus V Eupator - - - 164–162 - - - - - - - - - 10 - - - Demetrius I Soter - - - 162–150 - - - - - - - - - 11 - - - Alexander I Balas - - - 150–145 - - - - - - - - - 12 - - - Demetrius II Nicator - - - 145–138 - - - - - - - - - 13 - - - Antiochus VI Epiphanes - - - 145–142 - - - - - - - - - 14 - - - Antiochus VII Sidetes - - - 138–129 - - - - - - - - - 15 - - - Demetrius II Nicator - - - 129–125 - - - - - - - - - 16 - - - Alexander II Zabinas - - - 128–123 - - - - - - - - - 17 - - - Antiochus VIII Grypus - - - 125–96 - - - - - - - - - 18 - - - Seleucus V Philometor - - - 125 - - - - - - - - - 19 - - - Antiochus IX Cyzicenus - - - 116–96 - - - - - - - - - 20 - - - Demetrius III - - - 96–87 - - - - - - - - - 21 - - - Seleucus VI Epiphanes Nicator - - - 96–94 - - - - - - - - - 22 - - - Antiochus X Eusebes - - - 95–88? - - - - - - - - - 23 - - - Antiochus XI Epiphanes Philadelphus - - - 93? - - - - - - - - - 24 - - - Philip I - - - 94–83 - - - - - - - - - 25 - - - AntiochusXII Dionysus - - - 87–83 - - - - - - - - - 26 - - - Antiochus XIII Asiaticus - - - 69–64 - - - - - - - - - 27 - - - Philip II - - - 65–64 - - - - - - -
    - - - -

    - 17. Parthian or Arsacid Rulers -

    - - - - - 1 - - - Arsaces I - - - 247–211? - - - - - - - - - 2 - - - Arsaces II - - - 211?-191 - - - - - - - - - 3 - - - Phriapatius - - - 191–176 - - - - - - - - - 4 - - - Phraates I - - - 176–171 - - - - - - - - - 5 - - - Mithradates I - - - 171–138 - - - - - - - - - 6 - - - Phraates II - - - 138–128 - - - - - - - - - 7 - - - Artabanus I - - - 127–124 - - - - - - - - - 8 - - - Mithradates II - - - 124–88 - - - - - - - - - 9 - - - Gotarzes I - - - 91–80 - - - - - - - - - 10 - - - Orodes I - - - 80–75 - - - - - - - - - 11 - - - Sinatruces - - - 77–70 - - - - - - - - - 12 - - - Phraates III - - - 70–57 - - - - - - - - - 13 - - - Orodes II - - - 57–37 - - - - - - - - - 14 - - - Phraates IV - - - 37–2 - - - - - - - - - 15 - - - Phraates V - - - 2 BCE - 4 CE - - - - - - - - - 16 - - - Orodes III - - - 4–6 - - - - - - - - - 17 - - - Vonones - - - 8–12 - - - - - - - - - 18 - - - Artabanus II - - - 10–38 - - - - - - - - - 19 - - - Vardanes - - - 40–47 - - - - - - - - - 20 - - - Gotarzes II - - - 38–51 - - - - - - - - - 21 - - - Vologases I - - - 51–78 - - - - - - - - - 22 - - - Vologases II - - - 77–80 - - - - - - - - - 23 - - - Pacorus (II) - - - 78–105 - - - - - - - - - 24 - - - Artabanus III - - - 79–81 - - - - - - - - - 25 - - - Vologases III - - - 111–146 - - - - - - - - - 26 - - - Osroes - - - 109–129 - - - - - - - - - 27 - - - Vologases IV - - - 147–191 - - - - - - - - - 28 - - - Vologases V - - - 191–208 - - - - - - - - - 29 - - - Vologases VI - - - 207–226 - - - - - - - - - 30 - - - Artabanus IV - - - 216–224 - - - - - - - - - 31 - - - Tiridates - - - 226–228? - - - - - - -
    - - - -

    - 18. Rulers of Assyria -

    - - - - - 1 - - - Ṭudiya - - - - - - - - - - - - 2 - - - Adamu - - - - - - - - - - - - 3 - - - Yanqi - - - - - - - - - - - - 4 - - - Sahlamu - - - - - - - - - - - - 5 - - - Harharu - - - - - - - - - - - - 6 - - - Mandaru - - - - - - - - - - - - 7 - - - Imṣu - - - - - - - - - - - - 8 - - - HARṣu - - - - - - - - - - - - 9 - - - Didanu - - - - - - - - - - - - 10 - - - Hanu - - - - - - - - - - - - 11 - - - Zuabu - - - - - - - - - - - - 12 - - - Nuabu - - - - - - - - - - - - 13 - - - Abazu - - - - - - - - - - - - 14 - - - Belu - - - - - - - - - - - - 15 - - - Azarah - - - - - - - - - - - - 16 - - - Ušpiya - - - - - - - - - - - - 17 - - - Apiašal - - - - - - - - - - - - 18 - - - Hale - - - - - - - - - - - - 19 - - - Samanu - - - - - - - - - - - - 20 - - - Hayanu - - - - - - - - - - - - 21 - - - Ilu-Mer - - - - - - - - - - - - 22 - - - Yakmesi - - - - - - - - - - - - 23 - - - Yakmeni - - - - - - - - - - - - 24 - - - Yazkur-ilu - - - - - - - - - - - - 25 - - - Ila-kabkabi - - - - - - - - - - - - 26 - - - Aminu - - - - - - - - - - - - 27 - - - Sulili - - - - - - - - - - - - 28 - - - Kikkiya - - - - - - - - - - - - 29 - - - Akiya - - - - - - - - - - - - 30 - - - Puzur-Aššur I - - - - - - - - - - - - 31 - - - Šalim-ahum - - - - - - - - - - - - 32 - - - Ilušuma - - - - - - - - - - - - 33 - - - Erišum I - - - 1972–1933 - - (40) - - - - - - - 34 - - - Ikunum - - - 1932–1918 - - (15) - - - - - - - 35 - - - Sargon I - - - 1917–1878 - - (40) - - - - - - - 36 - - - Puzur-Aššur II - - - 1877–1870 - - (8) - - - - - - - 37 - - - Naram-Sin - - - 1869-(1836) - - (34) - - - - - - - 37a - - - Naram-Sin and Erišum II - - - 1835–1816 - - (20) - - - - - - - 38 - - - Erišum II - - - (1815)-1809 - - (7) - - - - - - - 39 - - - Šamši-Adad I - - - 1808–1776? - - (33?) - - - - - - - 40 - - - Išme-Dagan I - - - 1775?- - - (40) - - - - - - - 40a - - - Mut-Aškur - - - - - - - - - - - - 40b - - - Rimu-x - - - - - - - - - - - - 40c - - - Puzur-Sin - - - - - - - - - - - - 41 - - - Aššur-dugul - - - - - (6) - - - - - - - 42 - - - Aššur-apla-idi - - - - - - - - - - - - 43 - - - Naṣir-Sin - - - - - - - - - - - - 44 - - - Sin-namir - - - - - - - - - - - - 45 - - - Ipqi-Ištar - - - - - - - - - - - - 46 - - - Adad-ṣalulu - - - - - - - - - - - - 47 - - - Adasi - - - - - - - - - - - - 48 - - - Belu-bani - - - - - (10) - - - - - - - 49 - - - Libaya - - - - - (17) - - - - - - - 50 - - - Šarma-Adad I - - - - - (12) - - - - - - - 51 - - - IB.TAR-Sin - - - - - (12) - - - - - - - 52 - - - Bazaya - - - - - (28) - - - - - - - 53 - - - Lullaya - - - - - (6) - - - - - - - 54 - - - Kidin-Ninua - - - - - (14) - - - - - - - 55 - - - Šarma-Adad II - - - - - (3) - - - - - - - 56 - - - Erišum III - - - - - (13) - - - - - - - 57 - - - Šamši-Adad II - - - - - (6) - - - - - - - 58 - - - Išme-Dagan II - - - - - (16) - - - - - - - 59 - - - Šamši-Adad III - - - - - (16) - - - - - - - 60 - - - Aššur-nirari I - - - - - (26) - - - - - - - 61 - - - Puzur-Aššur III - - - - - (24?) - - - - - - - 62 - - - Enlil-naṣir I - - - - - (13) - - - - - - - 63 - - - Nur-ili - - - - - (12) - - - - - - - 64 - - - Aššur-šaduni - - - - - (1 month) - - - - - - - 65 - - - Aššur-rabi I - - - - - - - - - - - - 66 - - - Aššur-nadin-ahhe I - - - - - - - - - - - - 67 - - - Enlil-naṣir II - - - 1421–1416 - - (6) - - - - Length of reign is in lunar years of approximately 354 days. - -
    - } - placement="top" - /> - - - - - 68 - - - Aššur-nirari II - - - 1415–1409 - - (7) - - - - Length of reign is in lunar years of approximately 354 days. - - - } - placement="top" - /> - - - - - 69 - - - Aššur-bel-nišešu - - - 1408–1401 - - (9) - - - - Length of reign is in lunar years of approximately 354 days. - - - } - placement="top" - /> - - - - - 70 - - - Aššur-rem-nišešu - - - 1400–1393 - - (8) - - - - Length of reign is in lunar years of approximately 354 days. - - - } - placement="top" - /> - - - - - 71 - - - Aššur-nadin-ahhe II - - - 1392–1383 - - (10) - - - - Length of reign is in lunar years of approximately 354 days. - - - } - placement="top" - /> - - - - - 72 - - - Eriba-Adad I - - - 1382–1357 - - (27) - - - - Length of reign is in lunar years of approximately 354 days. - - - } - placement="top" - /> - - - - - 73 - - - Aššur-uballiṭ I - - - 1356–1322 - - (36) - - - - Length of reign is in lunar years of approximately 354 days. - - - } - placement="top" - /> - - - - - 74 - - - Enlil-nirari - - - 1321–1313 - - (10) - - - - Length of reign is in lunar years of approximately 354 days. - - - } - placement="top" - /> - - - - - 75 - - - Arik-den-ili - - - 1312–1301 - - (12) - - - - Length of reign is in lunar years of approximately 354 days. - - - } - placement="top" - /> - - - - - 76 - - - Adad-nirari I - - - 1300–1270 - - (32) - - - - Length of reign is in lunar years of approximately 354 days. - - - } - placement="top" - /> - - - - - 77 - - - Shalmaneser I - - - 1269–1241 - - (30) - - - - Length of reign is in lunar years of approximately 354 days. - - - } - placement="top" - /> - - - - - 78 - - - Tukulti-Ninurta I - - - 1240–1205 - - (37) - - - - Length of reign is in lunar years of approximately 354 days. - - - } - placement="top" - /> - - - - - 79 - - - Aššur-nadin-apli - - - 1204–1201 - - (4) - - - - Length of reign is in lunar years of approximately 354 days. - - - } - placement="top" - /> - - - - - 80 - - - Aššur-nirari III - - - 1200–1195 - - (6) - - - - Length of reign is in lunar years of approximately 354 days. - - - } - placement="top" - /> - - - - - 81 - - - Enlil-kudurri-uṣur - - - 1194–1190 - - (5) - - - - Length of reign is in lunar years of approximately 354 days. - - - } - placement="top" - /> - - - - - 82 - - - Ninurta-apil-Ekur - - - 1189–1178 - - (13) - - - - Length of reign is in lunar years of approximately 354 days. - - - } - placement="top" - /> - - - - - 83 - - - Aššur-dan I - - - 1177–1133 - - (46) - - - - Length of reign is in lunar years of approximately 354 days. - - - } - placement="top" - /> - - - - - 84 - - - Ninurta-tukulti-Aššur - - - 1132 - - (1) - - - - Length of reign is in a lunar year of approximately 354 days. - - - } - placement="top" - /> - - - - - 85 - - - Mutakkil-Nusku - - - 1131 - - (1) - - - - Length of reign is in a lunar year of approximately 354 days. - - - } - placement="top" - /> - - - - - 86 - - - Aššur-reš-iši I - - - 1130–1114 - - (18) - - - - Length of reign is in lunar years of approximately 354 days. - - - } - placement="top" - /> - - - - - 87 - - - Tiglath-pileser I - - - 1113–1076 - - (39) - - - - Length of reign is in lunar years of approximately 354 days. - - - } - placement="top" - /> - - - - - 88 - - - Ašared-apil-Ekur - - - 1075–1074 - - (2) - - - - Length of reign possibly in terms of a lunar year of 354 days. - - - } - placement="top" - /> - - - - - 89 - - - Aššur-bel-kala - - - 1073–1056 - - (18) - - - - Length of reign possibly in terms of a lunar year of 354 days. - - - } - placement="top" - /> - - - - - 90 - - - Eriba-Adad II - - - 1055–1054 - - (2) - - - - - - - 91 - - - Šamši-Adad IV - - - 1053–1050 - - (4) - - - - - - - 92 - - - Aššurnaṣirpal I - - - 1049–1031 - - (19) - - - - - - - 93 - - - Shalmaneser II - - - 1030–1019 - - (12) - - - - - - - 94 - - - Aššur-nirari IV - - - 1018–1013 - - (6) - - - - - - - 95 - - - Aššur-rabi II - - - 1012–972 - - (41) - - - - - - - 96 - - - Aššur-reš-iši II - - - 971–967 - - (5) - - - - - - - 97 - - - Tiglath-pileser II - - - 966–935 - - (32) - - - - - - - 98 - - - Aššur-dan II - - - 934–912 - - (23) - - - - - - - 99 - - - Adad-nirari II - - - 911–891 - - (21) - - - - - - - 100 - - - Tukulti-Ninurta II - - - 890–884 - - (7) - - - - - - - 101 - - - Aššurnaṣirpal II - - - 883–859 - - (25) - - - - - - - 102 - - - Shalmaneser III - - - 858–824 - - (35) - - - - - - - 103 - - - Šamši-Adad V - - - 823–811 - - (13) - - - - - - - 104 - - - Adad-nirari III - - - 810–783 - - (28) - - - - - - - 105 - - - Shalmaneser IV - - - 782–773 - - (10) - - - - - - - 106 - - - Aššur-dan III - - - 772–755 - - (18) - - - - - - - 107 - - - Aššur-nirari V - - - 754–745 - - (10) - - - - - - - 108 - - - Tiglath-pileser III - - - 744–727 - - (18) - - - - - - - 109 - - - Shalmaneser V - - - 726–722 - - (5) - - - - - - - 110 - - - Sargon II - - - 721–705 - - (17) - - - - - - - 111 - - - Sennacherib - - - 704–681 - - (24) - - - - - - - 112 - - - Esarhaddon - - - 680–669 - - (12) - - - - - - - 113 - - - Ashurbanipal - - - 668–631 - - (38?) - - - - - - - 114 - - - Aššur-etel-ilani - - - 630–627 - - (4) - - - - - - - 114a - - - Sin-šumu-lišir - - - 627? - - - - - - - - - 115 - - - Sin-šar-iškun - - - 626–612 - - (15?) - - - - - - - 116 - - - Aššur-uballiṭ II - - - 611–609 - - (3) - - - - - - - -`; diff --git a/src/router/aboutRoutes.tsx b/src/router/aboutRoutes.tsx index 2f6dc66d1..0476c1d4f 100644 --- a/src/router/aboutRoutes.tsx +++ b/src/router/aboutRoutes.tsx @@ -6,6 +6,8 @@ import { sitemapDefaults } from 'router/sitemap' import { HeadTagsService } from 'router/head' // ToDo: +// - Add route tests +// - Test change of url on click at about // - Update sitemap // console.log From 4d5ced66b0c9f6103dc9bc503f050dd18d64a649 Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Mon, 2 Oct 2023 21:32:12 +0000 Subject: [PATCH 40/91] Implement form functionality, design & refactor --- src/chronology/ui/DateConverterForm.sass | 28 ++ src/chronology/ui/DateConverterForm.tsx | 269 ++++++++++++------ .../ui/DateConverterFormFieldData.ts | 133 +++++++++ 3 files changed, 344 insertions(+), 86 deletions(-) create mode 100644 src/chronology/ui/DateConverterForm.sass create mode 100644 src/chronology/ui/DateConverterFormFieldData.ts diff --git a/src/chronology/ui/DateConverterForm.sass b/src/chronology/ui/DateConverterForm.sass new file mode 100644 index 000000000..bb2d2a28d --- /dev/null +++ b/src/chronology/ui/DateConverterForm.sass @@ -0,0 +1,28 @@ +.date_converter + padding-top: 50px + padding-bottom: 20px + +.section-row + align-items: stretch + border-bottom: 1px grey solid + padding-top: 10px + + .even + .section-title + + .odd + .section-title + +.section-row:last-child + border-bottom: none + +.section-title + writing-mode: vertical-rl + transform: rotate(180deg) + text-align: center + font-family: Arial, Helvetica, sans-serif + font-size: 80% + letter-spacing: 1px + +.section-fields + padding-left: 15px diff --git a/src/chronology/ui/DateConverterForm.tsx b/src/chronology/ui/DateConverterForm.tsx index 970770afe..5210391d2 100644 --- a/src/chronology/ui/DateConverterForm.tsx +++ b/src/chronology/ui/DateConverterForm.tsx @@ -1,103 +1,200 @@ import React, { useState } from 'react' +import { + Form, + FormGroup, + FormControl, + Row, + Col, + FormCheck, + FormLabel, + Popover, +} from 'react-bootstrap' +import DateConverter from 'chronology/domain/DateConverter' +import HelpTrigger from 'common/HelpTrigger' +import { sections, Field } from 'chronology/ui/DateConverterFormFieldData' +import './DateConverterForm.sass' +import { Markdown } from 'common/Markdown' -const fields = [ - { name: 'year', type: 'number', placeholder: 'Year', required: true }, - { name: 'bcYear', type: 'number', placeholder: 'BC Year' }, - { name: 'month', type: 'number', placeholder: 'Month', required: true }, - { name: 'day', type: 'number', placeholder: 'Day', required: true }, - { name: 'weekDay', type: 'number', placeholder: 'Week Day', required: true }, - { name: 'cjdn', type: 'number', placeholder: 'CJDN', required: true }, - { - name: 'lunationNabonassar', - type: 'number', - placeholder: 'Lunation Nabonassar', - required: true, - }, - { - name: 'seBabylonianYear', - type: 'number', - placeholder: 'SE Babylonian Year', - required: true, - }, - { - name: 'seMacedonianYear', - type: 'number', - placeholder: 'SE Macedonian Year', - }, - { name: 'seArsacidYear', type: 'number', placeholder: 'SE Arsacid Year' }, - { - name: 'mesopotamianMonth', - type: 'number', - placeholder: 'Mesopotamian Month', - required: true, - }, - { name: 'mesopotamianDay', type: 'number', placeholder: 'Mesopotamian Day' }, - { - name: 'mesopotamianMonthLength', - type: 'number', - placeholder: 'Mesopotamian Month Length', - }, - { name: 'ruler', type: 'text', placeholder: 'Ruler' }, - { name: 'regnalYear', type: 'number', placeholder: 'Regnal Year' }, -] +const description = `The project uses a date converter that is based on the converter developed by [Robert H. van Gent](https://webspace.science.uu.nl/~gent0113/babylon/babycal_converter.htm). +The form below presents a dedicated interface designed for users who need to convert dates between different ancient calendar systems. Users can choose from three different input scenarios for conversion: + +- **Modern Date**: For conversion related to contemporary dates. +- **Seleucid (Babylonian) Date**: For dates in the Seleucid or Babylonian calendar. +- **Nabonassar Date**: For dates in the Nabonassar calendar system. + +Each section of the form is dynamically updating based on the selected scenario. Fields that are relevant to the chosen scenario are highlighted for user convenience.` function DateForm(): JSX.Element { - const initialFormData = fields.reduce((acc, field) => { - acc[field.name] = '' - return acc - }, {}) + const dateConverter = new DateConverter() + const [formData, setFormData] = useState(dateConverter.calendar) + const [scenario, setScenario] = useState('setToModernDate') - /* ToDo: - Implement. - 1. Switch between scenarios. - 2. When a scenario is selected, only the inputs that are relevant should remain active. + const handleChange = (event) => { + const { name, value } = event.target + const _formData = { ...formData, [name]: value } + const { + year, + month, + day, + ruler, + regnalYear, + seBabylonianYear, + mesopotamianMonth, + mesopotamianDay, + } = _formData + const setSeBabylonianDateArgs = [ + seBabylonianYear, + mesopotamianMonth, + mesopotamianDay, + ] + const setMesopotamianDateArgs = [ + ruler, + regnalYear, + mesopotamianMonth, + mesopotamianDay, + ] + if (scenario === 'setToModernDate') { + dateConverter.setToModernDate( + year as number, + month as number, + day as number + ) + } else if ( + scenario === 'setSeBabylonianDate' && + !setSeBabylonianDateArgs.includes(undefined) + ) { + dateConverter.setSeBabylonianDate( + seBabylonianYear as number, + mesopotamianMonth as number, + mesopotamianDay as number + ) + } else if ( + scenario === 'setMesopotamianDate' && + !setMesopotamianDateArgs.includes(undefined) + ) { + dateConverter.setMesopotamianDate( + ruler as string, + regnalYear as number, + mesopotamianMonth as number, + mesopotamianDay as number + ) + } + setFormData({ ...dateConverter.calendar }) + } - Scenarios: - - * setToModernDate(year: number, month: number, day: number) - - * setSeBabylonianDate( - seBabylonianYear: number, - mesopotamianMonth: number, - mesopotamianDay: number - ) - - * setMesopotamianDate( - ruler: string, - regnalYear: number, - mesopotamianMonth: number, - mesopotamianDay: number - ) + const handleScenarioChange = (_scenario) => { + setScenario(_scenario) + } - */ + const fieldIsActive = (fieldName) => { + switch (scenario) { + case 'setToModernDate': + return ['year', 'month', 'day'].includes(fieldName) + case 'setSeBabylonianDate': + return [ + 'seBabylonianYear', + 'mesopotamianMonth', + 'mesopotamianDay', + ].includes(fieldName) + case 'setMesopotamianDate': + return [ + 'ruler', + 'regnalYear', + 'mesopotamianMonth', + 'mesopotamianDay', + ].includes(fieldName) + default: + return false + } + } + const activeStyle = { backgroundColor: '#f9ffcf' } - const [formData, setFormData] = useState(initialFormData) + function getField(field: Field, index: number): JSX.Element { + return ( + + + {field.placeholder}{' '} + + {field.help} + + } + /> + + + + ) + } + + function getSection( + title: string, + fields: Field[], + index: number + ): JSX.Element { + return ( + + +
    {title}
    + + + + {fields.map((field, fieldIndex) => getField(field, fieldIndex))} + + +
    + ) + } - const handleChange = (e) => { - const { name, value } = e.target - setFormData((prevState) => ({ ...prevState, [name]: value })) + const scenarioLabels = { + setToModernDate: 'Modern date', + setSeBabylonianDate: 'Seleucid (Babylonian) date', + setMesopotamianDate: 'Nabonassar date', } - const handleSubmit = (e) => { - e.preventDefault() - console.log(formData) + function getControls(): JSX.Element { + return ( + + ) } return ( -
    - {fields.map((field) => ( - - ))} - -
    + <> + + + +
    + {sections.map(({ title, fields }, index) => + getSection(title, fields, index) + )} +
    + + {getControls()} +
    + ) } diff --git a/src/chronology/ui/DateConverterFormFieldData.ts b/src/chronology/ui/DateConverterFormFieldData.ts new file mode 100644 index 000000000..193f06d00 --- /dev/null +++ b/src/chronology/ui/DateConverterFormFieldData.ts @@ -0,0 +1,133 @@ +const generalInformationFields = [ + { + name: 'year', + type: 'number', + placeholder: 'Year', + required: true, + help: + 'The modern (Gregorian) CE year. BCE years are displayed in negative numbers, e.g. -310 for 311 BCE.', + }, + { + name: 'bcYear', + type: 'number', + placeholder: 'BCE Year', + help: 'The modern (Gregorian) BCE year, if before CE.', + }, + { + name: 'month', + type: 'number', + placeholder: 'Month', + required: true, + help: 'The modern (Gregorian) month as a number from 1 to 12.', + }, + { + name: 'day', + type: 'number', + placeholder: 'Day', + required: true, + help: 'The modern (Gregorian) day of the month as a number from 1 to 31.', + }, + { + name: 'weekDay', + type: 'number', + placeholder: 'Week Day', + required: true, + help: + 'The modern (Gregorian) day of the week as a number from 1 (Monday) to 7 (Sunday).', + }, +] + +const specializedDateInformationFields = [ + { + name: 'cjdn', + type: 'number', + placeholder: 'CJDN', + required: true, + help: + 'Chronological Julian Day Number, a continuous count of days since the beginning of the Julian Period (November 24, 4714 BCE in the proleptic Gregorian calendar).', + }, + { + name: 'lunationNabonassar', + type: 'number', + placeholder: 'Lunation Nabonassar', + help: + 'Lunation following the Nabonassar (Nabû-nāṣir, 747-734 BCE) Era. Begins on Wednesday, February 26, 747 BCE.', + required: true, + }, +] + +const seleucidEraInformationFields = [ + { + name: 'seBabylonianYear', + type: 'number', + placeholder: 'SE Babylonian Year', + required: true, + help: 'Seleucid Era Babylonian year, counting from the year 312 BCE.', + }, + { + name: 'seMacedonianYear', + type: 'number', + placeholder: 'SE Macedonian Year', + help: 'Seleucid Era Macedonian year, counting from the year 312 BCE.', + }, + { + name: 'seArsacidYear', + type: 'number', + placeholder: 'SE Arsacid Year', + help: 'Year count during the Arsacid (Parthian) Dynasty, 247 BCE - 224 CE.', + }, +] + +const mesopotamianDateInformationFields = [ + { + name: 'ruler', + type: 'text', + placeholder: 'Ruler', + help: 'Name of the ruler or king reigning at the time.', + }, + { + name: 'regnalYear', + type: 'number', + placeholder: 'Regnal Year', + help: + 'Regnal year, or the year of the ruler’s reign, as a number starting from 1.', + }, + { + name: 'mesopotamianMonth', + type: 'number', + placeholder: 'Mesopotamian Month', + required: true, + help: + 'Mesopotamian month as a number from 1 to 12 or 13 (depending on the year).', + }, + { + name: 'mesopotamianDay', + type: 'number', + placeholder: 'Mesopotamian Day', + help: 'Mesopotamian day of the month as a number from 1 to 30.', + }, + { + name: 'mesopotamianMonthLength', + type: 'number', + placeholder: 'Mesopotamian Month Length', + help: 'Length of the Mesopotamian month, either 29 or 30 days.', + }, +] + +export const sections = [ + { title: 'Modern', fields: generalInformationFields }, + { title: 'Mesopotamian', fields: mesopotamianDateInformationFields }, + { title: 'Seleucid', fields: seleucidEraInformationFields }, + { + title: 'Specialized', + fields: specializedDateInformationFields, + }, +] + +export type Field = { + name: string + type: string + placeholder: string + required?: boolean + help: string +} From cac65542ad56db6e0560611078af45edc7e38dfe Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Tue, 3 Oct 2023 15:51:55 +0000 Subject: [PATCH 41/91] Add copy json button & refactor style --- src/chronology/ui/DateConverterForm.sass | 7 +++++++ src/chronology/ui/DateConverterForm.tsx | 18 ++++++++++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/chronology/ui/DateConverterForm.sass b/src/chronology/ui/DateConverterForm.sass index bb2d2a28d..8c113ef7b 100644 --- a/src/chronology/ui/DateConverterForm.sass +++ b/src/chronology/ui/DateConverterForm.sass @@ -26,3 +26,10 @@ .section-fields padding-left: 15px + +.active-field + background-color: #f9ffcf + +.copy-button + position: absolute + bottom: 100px diff --git a/src/chronology/ui/DateConverterForm.tsx b/src/chronology/ui/DateConverterForm.tsx index 5210391d2..a8e46bd6a 100644 --- a/src/chronology/ui/DateConverterForm.tsx +++ b/src/chronology/ui/DateConverterForm.tsx @@ -8,6 +8,7 @@ import { FormCheck, FormLabel, Popover, + Button, } from 'react-bootstrap' import DateConverter from 'chronology/domain/DateConverter' import HelpTrigger from 'common/HelpTrigger' @@ -15,6 +16,9 @@ import { sections, Field } from 'chronology/ui/DateConverterFormFieldData' import './DateConverterForm.sass' import { Markdown } from 'common/Markdown' +// ToDo: +// Fix errors. Note that changing the modern month moves the seleucid years (!). + const description = `The project uses a date converter that is based on the converter developed by [Robert H. van Gent](https://webspace.science.uu.nl/~gent0113/babylon/babycal_converter.htm). The form below presents a dedicated interface designed for users who need to convert dates between different ancient calendar systems. Users can choose from three different input scenarios for conversion: @@ -22,7 +26,7 @@ The form below presents a dedicated interface designed for users who need to con - **Seleucid (Babylonian) Date**: For dates in the Seleucid or Babylonian calendar. - **Nabonassar Date**: For dates in the Nabonassar calendar system. -Each section of the form is dynamically updating based on the selected scenario. Fields that are relevant to the chosen scenario are highlighted for user convenience.` +Each section of the form is dynamically updating based on the selected scenario. Fields that are relevant to the chosen scenario are highlighted for convenience.` function DateForm(): JSX.Element { const dateConverter = new DateConverter() @@ -107,7 +111,10 @@ function DateForm(): JSX.Element { return false } } - const activeStyle = { backgroundColor: '#f9ffcf' } + + const copyToClipboard = async () => { + await navigator.clipboard.writeText(JSON.stringify(formData)) + } function getField(field: Field, index: number): JSX.Element { return ( @@ -130,7 +137,7 @@ function DateForm(): JSX.Element { placeholder={field.placeholder} disabled={!fieldIsActive(field.name)} required={field.required && fieldIsActive(field.name)} - style={fieldIsActive(field.name) ? activeStyle : {}} + className={fieldIsActive(field.name) ? 'active-field' : ''} /> @@ -164,7 +171,7 @@ function DateForm(): JSX.Element { function getControls(): JSX.Element { return ( -
  • @@ -105,7 +105,7 @@ exports[`Snapshot 1`] = ` - Fanti & Carr, 2036: 8970824935538688-3796097900216320 + Fanti & Carr, 2037: 8970824935538688-3796097900216320 [ l. 4'.2., 2. ] @@ -120,7 +120,7 @@ exports[`Snapshot 1`] = ` - Hall & Reid, 2089: 7020923936833536-4895425479835648 + Hall & Reid, 2090: 7020923936833536-4895425479835648 [ l. 4'.2., 3'. ] @@ -5899,7 +5899,7 @@ exports[`Snapshot 1`] = ` - White & Manca, 2070: 6525764484726784-1000123435843584 + White & Manca, 2071: 6525764484726784-1000123435843584 [ l. 3'., 2. ] @@ -5918,7 +5918,7 @@ exports[`Snapshot 1`] = ` - Martinez & Robin, 2112: 5946678584541184-5595938733162496 + Martinez & Robin, 2113: 5946678584541184-5595938733162496 [ l. 3'., 4'.2. ] diff --git a/src/fragmentarium/ui/search/__snapshots__/FragmentariumSearch.test.tsx.snap b/src/fragmentarium/ui/search/__snapshots__/FragmentariumSearch.test.tsx.snap index 12338aa5c..f580f02ec 100644 --- a/src/fragmentarium/ui/search/__snapshots__/FragmentariumSearch.test.tsx.snap +++ b/src/fragmentarium/ui/search/__snapshots__/FragmentariumSearch.test.tsx.snap @@ -770,7 +770,7 @@ exports[`Searching fragments by transliteration Displays corpus results when cli - Giles & Alvarez, 2086: 5582194326110208-1406653725409280 + Giles & Alvarez, 2087: 5582194326110208-1406653725409280 [ l. 1., 3'. ] @@ -789,7 +789,7 @@ exports[`Searching fragments by transliteration Displays corpus results when cli - Shaw & Robert, 2045: 6150545542742016-5917511180615680 + Shaw & Robert, 2046: 6150545542742016-5917511180615680 [ l. 2., 1. ] @@ -6558,7 +6558,7 @@ exports[`Searching fragments by transliteration Displays corpus results when cli - Harrison & Palmieri, 2028: 5188341634957312-4059361584349184 + Harrison & Palmieri, 2029: 5188341634957312-4059361584349184 [ l. 1., 2. ] @@ -6577,7 +6577,7 @@ exports[`Searching fragments by transliteration Displays corpus results when cli - Wise & Hudson, 2039: 1529496131862528-4383736143544320 + Wise & Hudson, 2040: 1529496131862528-4383736143544320 [ l. 4'.2., 2. ] diff --git a/src/transliteration/ui/__snapshots__/markup.test.tsx.snap b/src/transliteration/ui/__snapshots__/markup.test.tsx.snap index b3a8aa722..df48a0dc2 100644 --- a/src/transliteration/ui/__snapshots__/markup.test.tsx.snap +++ b/src/transliteration/ui/__snapshots__/markup.test.tsx.snap @@ -40,7 +40,7 @@ exports[`Markup 1`] = ` - Dickinson & Falciani, 2062: 6831522153758720-8434983175716864 + Dickinson & Falciani, 2063: 6831522153758720-8434983175716864 [ l. 4'.2., 1. ] From 43d7c1e0a063b41e7dd9b5cc119855c18495e622 Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Tue, 2 Jan 2024 12:52:59 +0000 Subject: [PATCH 61/91] Update snapshots --- .../LatestTransliterations.test.tsx.snap | 16 ++++++++-------- .../FragmentariumSearch.test.tsx.snap | 12 ++++++------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/fragmentarium/ui/front-page/__snapshots__/LatestTransliterations.test.tsx.snap b/src/fragmentarium/ui/front-page/__snapshots__/LatestTransliterations.test.tsx.snap index d14edfa3a..598153a0b 100644 --- a/src/fragmentarium/ui/front-page/__snapshots__/LatestTransliterations.test.tsx.snap +++ b/src/fragmentarium/ui/front-page/__snapshots__/LatestTransliterations.test.tsx.snap @@ -71,9 +71,9 @@ exports[`Snapshot 1`] = ` , ) @@ -90,7 +90,7 @@ exports[`Snapshot 1`] = ` class="mesopotamian-date-display" role="time" > - 1.I.1 SE (3 April 311 BCE) + 1.I.1 SE (29 March 310 BCE PGC) @@ -108,7 +108,7 @@ exports[`Snapshot 1`] = ` - Fanti & Carr, 2036: 8970824935538688-3796097900216320 + Fanti & Carr, 2037: 8970824935538688-3796097900216320 [ l. 4'.2., 2. ] @@ -123,7 +123,7 @@ exports[`Snapshot 1`] = ` - Hall & Reid, 2089: 7020923936833536-4895425479835648 + Hall & Reid, 2090: 7020923936833536-4895425479835648 [ l. 4'.2., 3'. ] @@ -5888,7 +5888,7 @@ exports[`Snapshot 1`] = ` class="mesopotamian-date-display" role="time" > - 1.I.1 SE (3 April 311 BCE) + 1.I.1 SE (29 March 310 BCE PGC) @@ -5906,7 +5906,7 @@ exports[`Snapshot 1`] = ` - White & Manca, 2070: 6525764484726784-1000123435843584 + White & Manca, 2071: 6525764484726784-1000123435843584 [ l. 3'., 2. ] @@ -5925,7 +5925,7 @@ exports[`Snapshot 1`] = ` - Martinez & Robin, 2112: 5946678584541184-5595938733162496 + Martinez & Robin, 2113: 5946678584541184-5595938733162496 [ l. 3'., 4'.2. ] diff --git a/src/fragmentarium/ui/search/__snapshots__/FragmentariumSearch.test.tsx.snap b/src/fragmentarium/ui/search/__snapshots__/FragmentariumSearch.test.tsx.snap index 48d4a8c96..d598daf03 100644 --- a/src/fragmentarium/ui/search/__snapshots__/FragmentariumSearch.test.tsx.snap +++ b/src/fragmentarium/ui/search/__snapshots__/FragmentariumSearch.test.tsx.snap @@ -755,7 +755,7 @@ exports[`Searching fragments by transliteration Displays corpus results when cli class="mesopotamian-date-display" role="time" > - 1.I.1 SE (3 April 311 BCE) + 1.I.1 SE (29 March 310 BCE PGC) @@ -773,7 +773,7 @@ exports[`Searching fragments by transliteration Displays corpus results when cli - Giles & Alvarez, 2086: 5582194326110208-1406653725409280 + Giles & Alvarez, 2087: 5582194326110208-1406653725409280 [ l. 1., 3'. ] @@ -792,7 +792,7 @@ exports[`Searching fragments by transliteration Displays corpus results when cli - Shaw & Robert, 2045: 6150545542742016-5917511180615680 + Shaw & Robert, 2046: 6150545542742016-5917511180615680 [ l. 2., 1. ] @@ -6547,7 +6547,7 @@ exports[`Searching fragments by transliteration Displays corpus results when cli class="mesopotamian-date-display" role="time" > - 1.I.1 SE (3 April 311 BCE) + 1.I.1 SE (29 March 310 BCE PGC) @@ -6565,7 +6565,7 @@ exports[`Searching fragments by transliteration Displays corpus results when cli - Harrison & Palmieri, 2028: 5188341634957312-4059361584349184 + Harrison & Palmieri, 2029: 5188341634957312-4059361584349184 [ l. 1., 2. ] @@ -6584,7 +6584,7 @@ exports[`Searching fragments by transliteration Displays corpus results when cli - Wise & Hudson, 2039: 1529496131862528-4383736143544320 + Wise & Hudson, 2040: 1529496131862528-4383736143544320 [ l. 4'.2., 2. ] From 4bc979dda2d76a24bf31dcf07dd334963b1ed4d1 Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Tue, 2 Jan 2024 21:42:24 +0000 Subject: [PATCH 62/91] Add tests, refactor & extend options fields (WiP) --- .../DateConverterFormFieldData.ts | 3 +- src/chronology/ui/BrinkmanKings.tsx | 30 ++- src/chronology/ui/DateConverterForm.test.tsx | 44 ++++ src/chronology/ui/DateConverterForm.tsx | 2 +- src/chronology/ui/DateConverterFormField.tsx | 236 ++++++++++++++++++ src/chronology/ui/DateConverterFormParts.tsx | 160 +----------- 6 files changed, 306 insertions(+), 169 deletions(-) rename src/chronology/{ui => application}/DateConverterFormFieldData.ts (97%) create mode 100644 src/chronology/ui/DateConverterFormField.tsx diff --git a/src/chronology/ui/DateConverterFormFieldData.ts b/src/chronology/application/DateConverterFormFieldData.ts similarity index 97% rename from src/chronology/ui/DateConverterFormFieldData.ts rename to src/chronology/application/DateConverterFormFieldData.ts index 502a4c02a..ef8ef7931 100644 --- a/src/chronology/ui/DateConverterFormFieldData.ts +++ b/src/chronology/application/DateConverterFormFieldData.ts @@ -120,7 +120,8 @@ const mesopotamianDateInformationFields = [ name: 'mesopotamianDay', type: 'number', placeholder: 'Mesopotamian Day', - help: 'Mesopotamian day of the month as a number from 1 to 30.', + help: + 'Mesopotamian day of the month as a number from 1 to 29-30 (depending on the month).', }, { name: 'mesopotamianMonthLength', diff --git a/src/chronology/ui/BrinkmanKings.tsx b/src/chronology/ui/BrinkmanKings.tsx index 617ea0b99..45e2e0d37 100644 --- a/src/chronology/ui/BrinkmanKings.tsx +++ b/src/chronology/ui/BrinkmanKings.tsx @@ -6,7 +6,7 @@ import 'chronology/ui/BrinkmanKings.sass' import BrinkmanKings from 'chronology/domain/BrinkmanKings.json' import { Popover } from 'react-bootstrap' import HelpTrigger from 'common/HelpTrigger' -import Select from 'react-select' +import Select, { ValueType } from 'react-select' export interface King { orderGlobal: number @@ -101,20 +101,15 @@ export function KingField({ }: { king?: King setKing: React.Dispatch> - setIsCalenderFieldDisplayed: React.Dispatch> + setIsCalenderFieldDisplayed?: React.Dispatch> }): JSX.Element { return ( - onKingFieldChange(option, setKing, setIsCalenderFieldDisplayed) - } - isSearchable={true} - autoFocus={true} - placeholder="King" - value={king ? getCurrentKingOption(king) : undefined} - /> - ) -} - -const onKingFieldChange = ( - option: ValueType<{ label: string; value: King }, false>, - setKing: React.Dispatch>, - setIsCalenderFieldDisplayed?: React.Dispatch> -): void => { - setKing(option?.value) - if (setIsCalenderFieldDisplayed) { - if (option?.value?.dynastyNumber === '2') { - setIsCalenderFieldDisplayed(true) - } else { - setIsCalenderFieldDisplayed(false) - } - } -} - -function getKingSelectLabel(king: King): string { - const kingYears = king.date ? ` (${king.date})` : '' - return `${king.name}${kingYears}, ${king.dynastyName}` -} - -function getKingOptions(): Array<{ label: string; value: King }> { - return BrinkmanKings.filter( - (king) => !['16', '17'].includes(king.dynastyNumber) - ).map((king) => { - return { - label: getKingSelectLabel(king), - value: king, - } - }) -} - -function getCurrentKingOption( - king?: King -): { label: string; value: King } | undefined { - return kingOptions.find((kingOption) => _.isEqual(kingOption.value, king)) -} diff --git a/src/chronology/ui/BrinkmanKings/BrinkmanKingsTable.tsx b/src/chronology/ui/BrinkmanKings/BrinkmanKingsTable.tsx deleted file mode 100644 index 10cc4a5b9..000000000 --- a/src/chronology/ui/BrinkmanKings/BrinkmanKingsTable.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import React from 'react' -import { Markdown } from 'common/Markdown' -import BrinkmanKingsTable from 'chronology/ui/BrinkmanKings/BrinkmanKings' - -export default function AboutListOfKings(): JSX.Element { - return ( - <> - - - - ) -} diff --git a/src/chronology/ui/DateEditor/DateSelectionInput.tsx b/src/chronology/ui/DateEditor/DateSelectionInput.tsx index 5cb66218b..3384a0322 100644 --- a/src/chronology/ui/DateEditor/DateSelectionInput.tsx +++ b/src/chronology/ui/DateEditor/DateSelectionInput.tsx @@ -3,7 +3,7 @@ import _ from 'lodash' import { InputGroup, Form } from 'react-bootstrap' import Select from 'react-select' import { KingDateField, Ur3Calendar } from 'chronology/domain/DateBase' -import { King, KingField } from 'chronology/ui/BrinkmanKings/BrinkmanKings' +import { King, KingField } from 'chronology/ui/Kings/Kings' import { Eponym, EponymField } from 'chronology/ui/DateEditor/Eponyms' import getDateConfigs from 'chronology/application/DateSelectionInputConfig' import { diff --git a/src/chronology/ui/Kings/BrinkmanKingsTable.test.tsx b/src/chronology/ui/Kings/BrinkmanKingsTable.test.tsx new file mode 100644 index 000000000..a91204658 --- /dev/null +++ b/src/chronology/ui/Kings/BrinkmanKingsTable.test.tsx @@ -0,0 +1,20 @@ +import React from 'react' +import { render, screen } from '@testing-library/react' +import { Kings } from 'chronology/ui/Kings/Kings' +import ListOfKings from './BrinkmanKingsTable' + +test('Snapshot', () => { + expect(render().container).toMatchSnapshot() +}) + +test('Displays only kings from Brinkman in table', () => { + render() + expect( + Kings.filter( + (king) => + king.name === 'Gudea' && king.dynastyName === 'Second Dynasty of Lagash' + ).length + ).toBe(1) + expect(screen.queryByText('Second Dynasty of Lagash')).not.toBeInTheDocument() + expect(screen.queryByText('Gudea')).not.toBeInTheDocument() +}) diff --git a/src/chronology/ui/Kings/BrinkmanKingsTable.tsx b/src/chronology/ui/Kings/BrinkmanKingsTable.tsx new file mode 100644 index 000000000..0bf615162 --- /dev/null +++ b/src/chronology/ui/Kings/BrinkmanKingsTable.tsx @@ -0,0 +1,107 @@ +import React, { Fragment } from 'react' +import { Markdown } from 'common/Markdown' +import Table from 'react-bootstrap/Table' +import _ from 'lodash' +import 'chronology/ui/Kings/Kings.sass' +import { Popover } from 'react-bootstrap' +import HelpTrigger from 'common/HelpTrigger' +import { + King, + brinkmanDynasties, + getKingsByDynasty, +} from 'chronology/ui/Kings/Kings' + +export default function ListOfKings(): JSX.Element { + return ( + <> + + + + ) +} + +function BrinkmanKingsTable(): JSX.Element { + return ( + + + {brinkmanDynasties.map((dynastyName, index) => + getDynasty(dynastyName, index) + )} + +
    + ) +} + +function getDynasty( + dynastyName: string, + dynastyIndex: number, + brinkmanOnly = false +): JSX.Element { + const _kings = getKingsByDynasty(dynastyName).filter((king) => + brinkmanOnly ? !king.isNotInBrinkman : true + ) + const groups = _.countBy(_kings, 'groupWith') + const kingsTags = _kings.map((king) => getKing(king, groups)) + return ( + + + +

    {`${dynastyIndex + 1}. ${dynastyName}`}

    + + + {kingsTags} +
    + ) +} + +function getKing(king: King, groups): JSX.Element { + const rowSpan = groups[king.orderGlobal] ? groups[king.orderGlobal] + 1 : 1 + return ( + + + {king.orderInDynasty} + + + {king.name} + + {!king.groupWith && ( + + {`${king.date}`} {king.totalOfYears && `(${king.totalOfYears})`}{' '} + {king.notes && getNoteTrigger(king)} + + )} + + ) +} + +function getNoteTrigger(king: King): JSX.Element { + return ( + + {king.notes} + + } + /> + ) +} diff --git a/src/chronology/ui/BrinkmanKings/BrinkmanKings.sass b/src/chronology/ui/Kings/Kings.sass similarity index 100% rename from src/chronology/ui/BrinkmanKings/BrinkmanKings.sass rename to src/chronology/ui/Kings/Kings.sass diff --git a/src/chronology/ui/Kings/Kings.tsx b/src/chronology/ui/Kings/Kings.tsx new file mode 100644 index 000000000..0df879907 --- /dev/null +++ b/src/chronology/ui/Kings/Kings.tsx @@ -0,0 +1,101 @@ +import React from 'react' +import _ from 'lodash' +import 'chronology/ui/Kings/Kings.sass' +import _kings from 'chronology/domain/Kings.json' +import Select, { ValueType } from 'react-select' +import { KingDateField } from 'chronology/domain/DateBase' + +export interface King { + orderGlobal: number + groupWith?: number + dynastyNumber: string + dynastyName: string + orderInDynasty: string + name: string + date: string + totalOfYears: string + notes: string + isNotInBrinkman?: boolean +} + +export const Kings: King[] = _kings +const dynasties: string[] = _.uniq(_.map(Kings, 'dynastyName')) +export const brinkmanDynasties: string[] = dynasties.filter( + (dynastyName) => + !!getKingsByDynasty(dynastyName).every((king) => king.isNotInBrinkman) === + false +) + +export function getKingsByDynasty( + dynastyName: string +): King[] | KingDateField[] { + return _.filter(Kings, ['dynastyName', dynastyName]) +} + +export function findKingByOrderGlobal(orderGlobal: number): King | null { + const king = _.find(Kings, ['orderGlobal', orderGlobal]) + return king ?? null +} + +const kingOptions = getKingOptions() + +export function KingField({ + king, + setKing, + setIsCalenderFieldDisplayed, +}: { + king?: King | KingDateField + setKing: React.Dispatch> + setIsCalenderFieldDisplayed?: React.Dispatch> +}): JSX.Element { + return ( + > + setKing: React.Dispatch> setIsCalenderFieldDisplayed?: React.Dispatch> }): JSX.Element { return ( @@ -65,7 +65,7 @@ export function KingField({ const onKingFieldChange = ( option: ValueType<{ label: string; value: King }, false>, - setKing: React.Dispatch>, + setKing: React.Dispatch>, setIsCalenderFieldDisplayed?: React.Dispatch> ): void => { setKing(option?.value) @@ -95,7 +95,11 @@ function getKingOptions(): Array<{ label: string; value: King }> { } function getCurrentKingOption( - king?: King + king?: King | KingDateField ): { label: string; value: King } | undefined { + if (king && ('isBroken' in king || 'isUncertain' in king)) { + const { isBroken, isUncertain, ..._king } = king + king = _king + } return kingOptions.find((kingOption) => _.isEqual(kingOption.value, king)) } From 97d4294d1d7ab2c8de6769695aa3f1b37e43a9f6 Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Fri, 9 Feb 2024 14:54:38 +0000 Subject: [PATCH 80/91] Improve & refactor --- src/chronology/ui/DateDisplay.tsx | 50 ++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/src/chronology/ui/DateDisplay.tsx b/src/chronology/ui/DateDisplay.tsx index e8a6d71e4..1e91db568 100644 --- a/src/chronology/ui/DateDisplay.tsx +++ b/src/chronology/ui/DateDisplay.tsx @@ -7,6 +7,38 @@ interface Props { date: MesopotamianDate } +interface DateDisplayParams { + dateString: string + pjcDate: string + pgcDate: string + isDateSwitchable: boolean + tooltipMessage: string +} + +function getDateDisplayParams( + date: MesopotamianDate, + modernCalendar: 'PJC' | 'PGC' +): DateDisplayParams { + const parsedDate: string = date.toString() + const match = parsedDate.match(/(.*) \((.*) PJC \| (.*) PGC\)/) + const dateString = match ? match[1] : parsedDate + const pjcDate = match ? match[2] : '' + const pgcDate = match ? match[3] : '' + const isDateSwitchable = Boolean(match) + const tooltipMessage = + modernCalendar === 'PJC' + ? 'Switch to Proleptic Gregorian Calendar' + : 'Switch to Proleptic Julian Calendar' + + return { + dateString, + pjcDate, + pgcDate, + isDateSwitchable, + tooltipMessage, + } +} + const formatDateString = (dateString: string): ReactElement[] => { return dateString.split('?').map((part, index, array) => ( @@ -58,17 +90,13 @@ const DateDisplay: React.FC = ({ date }): ReactElement => { const toggleCalendar = (): void => { setModernCalendar((prev) => (prev === 'PJC' ? 'PGC' : 'PJC')) } - const parsedDate: string = date.toString() - const match = parsedDate.match(/(.*) \((.*) BCE PJC \| (.*) BCE PGC\)/) - const dateString = match ? match[1] : parsedDate - const pjcDate = match ? `${match[2]} BCE` : '' - const pgcDate = match ? `${match[3]} BCE` : '' - const isDateSwitchable = Boolean(match) - const tooltipMessage = - modernCalendar === 'PJC' - ? 'Switch to Proleptic Gregorian Calendar' - : 'Switch to Proleptic Julian Calendar' - + const { + dateString, + pjcDate, + pgcDate, + isDateSwitchable, + tooltipMessage, + } = getDateDisplayParams(date, modernCalendar) return (
    {formatDateString(dateString)} From 8a1fcfaff2bac3f17ee8c5dfba36960bb50aae1b Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Fri, 9 Feb 2024 15:31:50 +0000 Subject: [PATCH 81/91] Add tests --- src/chronology/ui/Kings/Kings.test.tsx | 62 ++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/chronology/ui/Kings/Kings.test.tsx diff --git a/src/chronology/ui/Kings/Kings.test.tsx b/src/chronology/ui/Kings/Kings.test.tsx new file mode 100644 index 000000000..0ea7362b3 --- /dev/null +++ b/src/chronology/ui/Kings/Kings.test.tsx @@ -0,0 +1,62 @@ +import React from 'react' +import { render, screen } from '@testing-library/react' +import userEvent from '@testing-library/user-event' +import { getKingsByDynasty, findKingByOrderGlobal, KingField } from './Kings' + +describe('getKingsByDynasty', () => { + it('returns kings from the specified dynasty', () => { + const result = getKingsByDynasty('Dynasty of Akkad') + expect(result).toEqual( + expect.arrayContaining([ + expect.objectContaining({ dynastyName: 'Dynasty of Akkad' }), + ]) + ) + }) + + it('returns an empty array for a dynasty that does not exist', () => { + const result = getKingsByDynasty('Nonexistent Dynasty') + expect(result).toHaveLength(0) + }) +}) + +describe('findKingByOrderGlobal', () => { + it('finds and returns the king with the specified orderGlobal', () => { + const result = findKingByOrderGlobal(1) + expect(result).toEqual(expect.objectContaining({ name: 'Sargon' })) + }) + + it('returns null if no king with the specified orderGlobal exists', () => { + const result = findKingByOrderGlobal(999) + expect(result).toBeNull() + }) +}) + +describe('KingField Component', () => { + it('renders without crashing', () => { + // eslint-disable-next-line @typescript-eslint/no-empty-function + render( {}} />) + expect(screen.getByLabelText(/select-king/i)).toBeInTheDocument() + }) + + it('updates the king selection', async () => { + const setKing = jest.fn() + render() + const selectInput = screen.getByLabelText(/select-king/i) + await userEvent.type(selectInput, 'Sargon', { skipClick: true }) + await userEvent.keyboard('{arrowdown}') + await userEvent.keyboard('{enter}') + + expect(setKing).toHaveBeenCalledWith( + expect.objectContaining({ + date: '709–705', + dynastyName: 'Miscellaneous Dynasties', + dynastyNumber: '12', + name: 'Sargon II', + notes: '', + orderGlobal: 147, + orderInDynasty: '22', + totalOfYears: '5', + }) + ) + }) +}) From 5dea98ea1270678702348ee99965a6f93d343f12 Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Mon, 12 Feb 2024 19:37:28 +0000 Subject: [PATCH 82/91] Implement validation & date display in editor --- src/chronology/application/DateSelection.tsx | 64 ++++++++++++++++--- .../ui/DateEditor/DateSelection.test.tsx | 5 +- .../DateEditor/DatesInTextSelection.test.tsx | 8 +++ 3 files changed, 68 insertions(+), 9 deletions(-) diff --git a/src/chronology/application/DateSelection.tsx b/src/chronology/application/DateSelection.tsx index 13cff382c..4a3fce987 100644 --- a/src/chronology/application/DateSelection.tsx +++ b/src/chronology/application/DateSelection.tsx @@ -14,6 +14,7 @@ import { } from 'chronology/ui/DateEditor/DateSelectionInput' import useDateSelectionState, { DateEditorStateProps, + DateSelectionState, } from 'chronology/application/DateSelectionState' type Props = { @@ -30,6 +31,28 @@ interface DateEditorProps extends DateEditorStateProps { isDisplayed: boolean } +function getSelectedDateAndValidation( + state: DateSelectionState, + savedDate?: MesopotamianDate +): { selectedDate?: MesopotamianDate; isSelectedDateValid: boolean } { + let isSelectedDateValid: boolean + let selectedDate: MesopotamianDate | undefined + try { + selectedDate = state.getDate() + const dateString = selectedDate.toString() + const isDatesNotSame = + savedDate === undefined || dateString !== savedDate.toString() + const isDateEmpty = dateString.replaceAll('SE', '') !== '' + const isAssyrianDateNotEmpty = + !state.isAssyrianDate || dateString !== '∅.∅.1' + isSelectedDateValid = + isDateEmpty && isAssyrianDateNotEmpty && isDatesNotSame + } catch { + isSelectedDateValid = false + } + return { selectedDate, isSelectedDateValid } +} + export function DateEditor({ date, setDate, @@ -55,27 +78,50 @@ export function DateEditor({ const dateOptionsInput = DateOptionsInput({ ...state }) const dateInputGroups = DateInputGroups({ ...state }) - const saveButton = ( + const deleteButton = ( ) - const deleteButton = ( + const { selectedDate, isSelectedDateValid } = getSelectedDateAndValidation( + state, + date + ) + + const saveButton = ( ) + const savedDateDisplay = date ? ( + <> + Saved date + + + ) : ( + '' + ) + const selectedDateDisplay = + selectedDate && isSelectedDateValid ? ( + <> + Selected date + + + ) : ( + '' + ) + const popover = ( {dateOptionsInput} {dateInputGroups} + {savedDateDisplay} + {selectedDateDisplay} {date && deleteButton} {saveButton} Saving... diff --git a/src/chronology/ui/DateEditor/DateSelection.test.tsx b/src/chronology/ui/DateEditor/DateSelection.test.tsx index af0fc2c46..454588cc6 100644 --- a/src/chronology/ui/DateEditor/DateSelection.test.tsx +++ b/src/chronology/ui/DateEditor/DateSelection.test.tsx @@ -126,8 +126,11 @@ describe('DateSelection', () => { act(() => { fireEvent.click(editButton) }) + const yearInput = screen.getByPlaceholderText('Year') + await act(async () => { + fireEvent.change(yearInput, { target: { value: '189' } }) + }) const saveButton = screen.getByText('Save') - fireEvent.click(saveButton) const loadingSpinner = screen.getByText('Saving...') expect(loadingSpinner).toBeInTheDocument() diff --git a/src/chronology/ui/DateEditor/DatesInTextSelection.test.tsx b/src/chronology/ui/DateEditor/DatesInTextSelection.test.tsx index 99a778be9..b565ff688 100644 --- a/src/chronology/ui/DateEditor/DatesInTextSelection.test.tsx +++ b/src/chronology/ui/DateEditor/DatesInTextSelection.test.tsx @@ -44,6 +44,10 @@ describe('DatesInTextSelection', () => { await act(async () => { fireEvent.click(addButton) }) + const yearInput = screen.getByPlaceholderText('Year') + await act(async () => { + fireEvent.change(yearInput, { target: { value: '189' } }) + }) const saveButton = screen.getByText('Save') await act(async () => { fireEvent.click(saveButton) @@ -62,6 +66,10 @@ describe('DatesInTextSelection', () => { await act(async () => { fireEvent.click(editButton) }) + const yearInput = screen.getByPlaceholderText('Year') + await act(async () => { + fireEvent.change(yearInput, { target: { value: '189' } }) + }) const saveButton = screen.getByText('Save') await act(async () => { fireEvent.click(saveButton) From 27dde9cd41aa9b30b77a245bf8c15b8ed7e889e3 Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Tue, 13 Feb 2024 19:13:31 +0000 Subject: [PATCH 83/91] Update tests --- .../ui/DateEditor/DatesInTextSelection.test.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/chronology/ui/DateEditor/DatesInTextSelection.test.tsx b/src/chronology/ui/DateEditor/DatesInTextSelection.test.tsx index b565ff688..ba13c69fa 100644 --- a/src/chronology/ui/DateEditor/DatesInTextSelection.test.tsx +++ b/src/chronology/ui/DateEditor/DatesInTextSelection.test.tsx @@ -44,9 +44,11 @@ describe('DatesInTextSelection', () => { await act(async () => { fireEvent.click(addButton) }) - const yearInput = screen.getByPlaceholderText('Year') + const dayInput = screen.getByPlaceholderText('Day') + const monthInput = screen.getByPlaceholderText('Month') await act(async () => { - fireEvent.change(yearInput, { target: { value: '189' } }) + fireEvent.change(dayInput, { target: { value: '18' } }) + fireEvent.change(monthInput, { target: { value: '10' } }) }) const saveButton = screen.getByText('Save') await act(async () => { @@ -66,9 +68,11 @@ describe('DatesInTextSelection', () => { await act(async () => { fireEvent.click(editButton) }) - const yearInput = screen.getByPlaceholderText('Year') + const dayInput = screen.getByPlaceholderText('Day') + const monthInput = screen.getByPlaceholderText('Month') await act(async () => { - fireEvent.change(yearInput, { target: { value: '189' } }) + fireEvent.change(dayInput, { target: { value: '18' } }) + fireEvent.change(monthInput, { target: { value: '10' } }) }) const saveButton = screen.getByText('Save') await act(async () => { From 6c06c049f8ebe48018378f11b8f5bb4b7dc3006e Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Thu, 22 Feb 2024 12:02:37 +0000 Subject: [PATCH 84/91] Refactor --- src/chronology/domain/DateBase.ts | 35 ++++++++++--------------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/src/chronology/domain/DateBase.ts b/src/chronology/domain/DateBase.ts index 09e276f46..47261a9fd 100644 --- a/src/chronology/domain/DateBase.ts +++ b/src/chronology/domain/DateBase.ts @@ -95,23 +95,19 @@ export class MesopotamianDateBase { } toModernDate(calendar: 'Julian' | 'Gregorian' = 'Julian'): string { - const { year, month, day, isApproximate } = this.getDateApproximation() const dateProps = { - year, - month, - day, - isApproximate, + ...this.getDateApproximation(), calendar, } let julianDate = '' - if (this.isSeleucidEraApplicable(year)) { + if (this.isSeleucidEraApplicable(dateProps.year)) { julianDate = this.seleucidToModernDate(dateProps) } else if (this.isNabonassarEraApplicable()) { julianDate = this.getNabonassarEraDate(dateProps) } else if (this.isAssyrianDateApplicable()) { julianDate = this.getAssyrianDate({ calendar: 'Julian' }) } else if (this.isKingDateApplicable()) { - julianDate = this.kingToModernDate({ year, calendar: 'Julian' }) + julianDate = this.kingToModernDate({ ...dateProps, calendar: 'Julian' }) } return julianDate } @@ -144,24 +140,14 @@ export class MesopotamianDateBase { day: number isApproximate: boolean } { - let year = parseInt(this.year.value) - let month = parseInt(this.month.value) - let day = parseInt(this.day.value) - const isApproximate = this.isApproximate() - if (isNaN(month)) { - month = 1 - } - if (isNaN(day)) { - day = 1 - } - if (isNaN(year)) { - year = -1 - } + const year = parseInt(this.year.value) + const month = parseInt(this.month.value) + const day = parseInt(this.day.value) return { - year, - month, - day, - isApproximate: isApproximate, + year: isNaN(year) ? -1 : year, + month: isNaN(month) ? 1 : month, + day: isNaN(day) ? 1 : day, + isApproximate: this.isApproximate(), } } @@ -221,6 +207,7 @@ export class MesopotamianDateBase { } return '' } + private kingToModernDate({ year, calendar = 'Julian', From 29d3eab58998b749b7eee7f78035a9381da424ee Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Thu, 22 Feb 2024 20:17:45 +0000 Subject: [PATCH 85/91] Update date calculations & tests --- .../DateConverterFormChange.test.ts | 2 +- src/chronology/domain/Date.test.ts | 14 ++++----- src/chronology/domain/DateConverter.test.ts | 29 +++++++++---------- src/chronology/domain/DateConverterCompute.ts | 26 ++++++++--------- .../DateConverter/DateConverterForm.test.tsx | 10 +++---- .../ui/DateConverter/DateConverterForm.tsx | 1 - 6 files changed, 39 insertions(+), 43 deletions(-) diff --git a/src/chronology/application/DateConverterFormChange.test.ts b/src/chronology/application/DateConverterFormChange.test.ts index ac9e65e9a..f26f5026f 100644 --- a/src/chronology/application/DateConverterFormChange.test.ts +++ b/src/chronology/application/DateConverterFormChange.test.ts @@ -51,7 +51,7 @@ it('handles setToGregorianDate scenario correctly', () => { setFormData: mockSetFormData, setScenario, }) - expect(mockDateConverter.setToGregorianDate).toBeCalledWith(-309, 3, 29) + expect(mockDateConverter.setToGregorianDate).toBeCalledWith(-310, 3, 29) }) it('handles setToJulianDate scenario correctly', () => { diff --git a/src/chronology/domain/Date.test.ts b/src/chronology/domain/Date.test.ts index 9339b703b..5cdf8fc42 100644 --- a/src/chronology/domain/Date.test.ts +++ b/src/chronology/domain/Date.test.ts @@ -109,7 +109,7 @@ describe('MesopotamianDate', () => { true ) expect(date.toString()).toBe( - '12.V.10 SE (30 August 302 BCE PJC | 25 August 301 BCE PGC)' + '12.V.10 SE (30 August 302 BCE PJC | 25 August 302 BCE PGC)' ) }) @@ -123,7 +123,7 @@ describe('MesopotamianDate', () => { true ) expect(date.toString()).toBe( - '∅.V.10 SE (ca. 19 August 302 BCE PJC | ca. 14 August 301 BCE PGC)' + '∅.V.10 SE (ca. 19 August 302 BCE PJC | ca. 14 August 302 BCE PGC)' ) }) @@ -137,7 +137,7 @@ describe('MesopotamianDate', () => { true ) expect(date.toString()).toBe( - '12.∅.10 SE (ca. 4 May 302 BCE PJC | ca. 29 April 301 BCE PGC)' + '12.∅.10 SE (ca. 4 May 302 BCE PJC | ca. 29 April 302 BCE PGC)' ) }) @@ -164,7 +164,7 @@ describe('MesopotamianDate', () => { false ) expect(date.toString()).toBe( - '12.V.10 Darius I (11 August 512 BCE PJC | 5 August 511 BCE PGC)' + '12.V.10 Darius I (11 August 512 BCE PJC | 5 August 512 BCE PGC)' ) }) @@ -179,7 +179,7 @@ describe('MesopotamianDate', () => { false ) expect(date.toString()).toBe( - '∅.V.10 Darius I (ca. 31 July 512 BCE PJC | ca. 25 July 511 BCE PGC)' + '∅.V.10 Darius I (ca. 31 July 512 BCE PJC | ca. 25 July 512 BCE PGC)' ) }) @@ -194,7 +194,7 @@ describe('MesopotamianDate', () => { false ) expect(date.toString()).toBe( - '12.∅.10 Darius I (ca. 16 April 512 BCE PJC | ca. 10 April 511 BCE PGC)' + '12.∅.10 Darius I (ca. 16 April 512 BCE PJC | ca. 10 April 512 BCE PGC)' ) }) @@ -209,7 +209,7 @@ describe('MesopotamianDate', () => { false ) expect(date.toString()).toBe( - '∅.V.10 Darius I (ca. 31 July 512 BCE PJC | ca. 25 July 511 BCE PGC)' + '∅.V.10 Darius I (ca. 31 July 512 BCE PJC | ca. 25 July 512 BCE PGC)' ) }) diff --git a/src/chronology/domain/DateConverter.test.ts b/src/chronology/domain/DateConverter.test.ts index 7ff86ecd5..5b46ab542 100644 --- a/src/chronology/domain/DateConverter.test.ts +++ b/src/chronology/domain/DateConverter.test.ts @@ -3,8 +3,8 @@ import DateConverter from 'chronology/domain/DateConverter' const dateJulianEraBegin = { bcJulianYear: 311, cjdn: 1607923, - gregorianYear: -309, - bcGregorianYear: 310, + gregorianYear: -310, + bcGregorianYear: 311, gregorianMonth: 3, gregorianDay: 29, julianDay: 3, @@ -23,8 +23,8 @@ const dateJulianEraBegin = { } const dateNebuchadnezzarIIY43M12D28 = { - gregorianYear: -559, - bcGregorianYear: 560, + gregorianYear: -560, + bcGregorianYear: 561, gregorianMonth: 3, gregorianDay: 28, julianYear: -560, @@ -44,8 +44,8 @@ const dateNebuchadnezzarIIY43M12D28 = { } const dateNebuchadnezzarIIY23M10D14 = { - gregorianYear: -580, - bcGregorianYear: 581, + gregorianYear: -581, + bcGregorianYear: 582, gregorianMonth: 12, gregorianDay: 28, julianYear: -580, @@ -65,8 +65,8 @@ const dateNebuchadnezzarIIY23M10D14 = { } const dateSeleucidY100M12D26 = { - gregorianYear: -209, - bcGregorianYear: 210, + gregorianYear: -210, + bcGregorianYear: 211, gregorianMonth: 3, gregorianDay: 30, julianYear: -210, @@ -89,7 +89,6 @@ const dateSeleucidY100M12D26 = { describe('DateConverter', () => { let mesopotamianDate: DateConverter - beforeEach(() => { mesopotamianDate = new DateConverter() }) @@ -97,7 +96,7 @@ describe('DateConverter', () => { test('Check initial state', () => { const expected = dateJulianEraBegin expect(mesopotamianDate.calendar).toEqual(expected) - expect(mesopotamianDate.toDateString()).toEqual('29 March 310 BCE PGC') + expect(mesopotamianDate.toDateString()).toEqual('29 March 311 BCE PGC') expect(mesopotamianDate.toDateString('Julian')).toEqual( '3 April 311 BCE PJC' ) @@ -105,9 +104,9 @@ describe('DateConverter', () => { test('Set to Gregorian date', () => { const expected = dateNebuchadnezzarIIY43M12D28 - mesopotamianDate.setToGregorianDate(-559, 3, 28) + mesopotamianDate.setToGregorianDate(-560, 3, 28) expect(mesopotamianDate.calendar).toEqual(expected) - expect(mesopotamianDate.toDateString()).toEqual('28 March 560 BCE PGC') + expect(mesopotamianDate.toDateString()).toEqual('28 March 561 BCE PGC') expect(mesopotamianDate.toDateString('Julian')).toEqual( '3 April 561 BCE PJC' ) @@ -117,7 +116,7 @@ describe('DateConverter', () => { const expected = dateNebuchadnezzarIIY43M12D28 mesopotamianDate.setToJulianDate(-560, 4, 3) expect(mesopotamianDate.calendar).toEqual(expected) - expect(mesopotamianDate.toDateString()).toEqual('28 March 560 BCE PGC') + expect(mesopotamianDate.toDateString()).toEqual('28 March 561 BCE PGC') expect(mesopotamianDate.toDateString('Julian')).toEqual( '3 April 561 BCE PJC' ) @@ -127,7 +126,7 @@ describe('DateConverter', () => { const expected = dateNebuchadnezzarIIY23M10D14 mesopotamianDate.setToMesopotamianDate('Nebuchadnezzar II', 23, 10, 14) expect(mesopotamianDate.calendar).toEqual(expected) - expect(mesopotamianDate.toDateString()).toEqual('28 December 581 BCE PGC') + expect(mesopotamianDate.toDateString()).toEqual('28 December 582 BCE PGC') expect(mesopotamianDate.toDateString('Julian')).toEqual( '3 January 581 BCE PJC' ) @@ -137,7 +136,7 @@ describe('DateConverter', () => { mesopotamianDate.setToSeBabylonianDate(100, 12, 26) const expected = dateSeleucidY100M12D26 expect(mesopotamianDate.calendar).toEqual(expected) - expect(mesopotamianDate.toDateString()).toEqual('30 March 210 BCE PGC') + expect(mesopotamianDate.toDateString()).toEqual('30 March 211 BCE PGC') expect(mesopotamianDate.toDateString('Julian')).toEqual( '3 April 211 BCE PJC' ) diff --git a/src/chronology/domain/DateConverterCompute.ts b/src/chronology/domain/DateConverterCompute.ts index 06b2d19ee..1187b4769 100644 --- a/src/chronology/domain/DateConverterCompute.ts +++ b/src/chronology/domain/DateConverterCompute.ts @@ -64,7 +64,7 @@ export default class DateConverterCompute { ) const { quotient: alpha2b, remainder: m0 } = divmod(m1 + 2, 12) return { - year: a1 + alpha2b < 1 ? a1 + alpha2b + 1 : a1 + alpha2b, + year: a1 + alpha2b < 1 ? a1 + alpha2b : a1 + alpha2b, month: m0 + 1, day: Math.floor(epsilon1 / 5) + 1, } @@ -111,19 +111,17 @@ export default class DateConverterCompute { gregorianMonth: number gregorianDay: number }): number { - gregorianYear = gregorianYear < 1 ? gregorianYear - 1 : gregorianYear - const alpha1 = Math.floor((gregorianMonth - 3) / 12) - const m1 = (gregorianMonth - 3) % 12 - const a1 = gregorianYear + alpha1 - return ( - 365 * a1 + - Math.floor(a1 / 4) - - Math.floor(a1 / 100) + - Math.floor(a1 / 400) + - Math.floor((153 * m1 + 2) / 5) + - gregorianDay + - 1721119 - ) + if (gregorianMonth < 3) { + gregorianYear -= 1 + gregorianMonth += 12 + } + gregorianYear = gregorianYear === 0 ? -1 : gregorianYear + const monthDays = Math.floor(30.6001 * (gregorianMonth + 1)) + const century = Math.floor(gregorianYear / 100) + const leapYearCorrection = Math.floor(century / 4) + const fixedDay = 2 - century + leapYearCorrection + const yearDays = Math.floor(365.25 * (gregorianYear + 4716)) + return Math.floor(fixedDay + gregorianDay + yearDays + monthDays - 1524) } computeWeekDay(cjdn: number): number { diff --git a/src/chronology/ui/DateConverter/DateConverterForm.test.tsx b/src/chronology/ui/DateConverter/DateConverterForm.test.tsx index 79fa9ccb5..d1c0a92e6 100644 --- a/src/chronology/ui/DateConverter/DateConverterForm.test.tsx +++ b/src/chronology/ui/DateConverter/DateConverterForm.test.tsx @@ -62,7 +62,7 @@ describe('DateConverterForm', () => { expect(screen.getAllByLabelText(/cjdn|lunation/i)).toHaveLength(2) expect(optionToArray(screen.getByLabelText('Ruler'))).toStrictEqual(29) expect(screen.getAllByLabelText(/year/i).map(optionToArray)).toStrictEqual([ - 701, + 702, 702, 30, 701, @@ -82,7 +82,7 @@ describe('DateConverterForm', () => { it('renders initial form values correctly', () => { render() - expect(screen.getByLabelText('Year')).toHaveValue('-309') + expect(screen.getByLabelText('Year')).toHaveValue('-310') expect(screen.getByLabelText('Month')).toHaveValue('3') expect(screen.getByLabelText('Day')).toHaveValue('29') expect(screen.getByLabelText('Julian Year')).toHaveValue('-310') @@ -140,7 +140,7 @@ describe('DateConverterForm', () => { within(screen.getByLabelText('Year')).getByText('300 BCE') ) }) - expect(screen.getByLabelText('Year')).toHaveValue('-309') + expect(screen.getByLabelText('Year')).toHaveValue('-310') expect(screen.getByLabelText('Month')).toHaveValue('3') expect(screen.getByLabelText('Day')).toHaveValue('29') expect(screen.getByLabelText('Julian Year')).toHaveValue('-310') @@ -164,7 +164,7 @@ describe('DateConverterForm', () => { fireEvent.click(screen.getByText('Copy JSON')) }) const expected = { - gregorianYear: -309, + gregorianYear: -310, gregorianMonth: 3, gregorianDay: 29, julianYear: -310, @@ -176,7 +176,7 @@ describe('DateConverterForm', () => { seBabylonianYear: 1, lunationNabonassar: 5395, bcJulianYear: 311, - bcGregorianYear: 310, + bcGregorianYear: 311, mesopotamianDay: 1, mesopotamianMonthLength: 29, ruler: 'Seleucus I Nicator', diff --git a/src/chronology/ui/DateConverter/DateConverterForm.tsx b/src/chronology/ui/DateConverter/DateConverterForm.tsx index 292bb04a0..978183b65 100644 --- a/src/chronology/ui/DateConverter/DateConverterForm.tsx +++ b/src/chronology/ui/DateConverter/DateConverterForm.tsx @@ -15,7 +15,6 @@ import { handleDateConverterFormChange } from 'chronology/application/DateConver // ToDo: // - Errors: -// - January & February have issues (both Julean & Gregorian date drifts upon change) // - Check dates around 1 BCE / CE // - Fix errors with first and last ruler From 90edf1b6df9c2ea0f6dc8f418ca5f897831f935d Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Fri, 23 Feb 2024 18:18:05 +0000 Subject: [PATCH 86/91] Implement date ranges (WiP) --- src/chronology/domain/Date.test.ts | 287 ++++++++---------- src/chronology/domain/Date.ts | 21 +- src/chronology/domain/DateBase.ts | 32 +- src/chronology/domain/DateRange.ts | 28 ++ .../DateEditor/DatesInTextSelection.test.tsx | 1 - src/test-support/date-fixtures.ts | 10 +- src/test-support/fragment-fixtures.ts | 14 +- src/test-support/test-fragment.ts | 28 +- 8 files changed, 210 insertions(+), 211 deletions(-) create mode 100644 src/chronology/domain/DateRange.ts diff --git a/src/chronology/domain/Date.test.ts b/src/chronology/domain/Date.test.ts index 5cdf8fc42..de1284aaf 100644 --- a/src/chronology/domain/Date.test.ts +++ b/src/chronology/domain/Date.test.ts @@ -89,157 +89,135 @@ describe('MesopotamianDate', () => { describe('converts to string', () => { it('returns the correct string representation (standard)', () => { - const date = new MesopotamianDate( - { value: '10' }, - { value: '5' }, - { value: '12' }, - king - ) + const date = new MesopotamianDate({ + year: { value: '10' }, + month: { value: '5' }, + day: { value: '12' }, + king, + }) expect(date.toString()).toBe('12.V.10 Sargon (ca. 2325 BCE PJC)') }) }) it('returns the correct string representation (Seleucid)', () => { - const date = new MesopotamianDate( - { value: '10' }, - { value: '5' }, - { value: '12' }, - undefined, - undefined, - true - ) + const date = new MesopotamianDate({ + year: { value: '10' }, + month: { value: '5' }, + day: { value: '12' }, + isSeleucidEra: true, + }) expect(date.toString()).toBe( '12.V.10 SE (30 August 302 BCE PJC | 25 August 302 BCE PGC)' ) }) it('returns the correct string representation (Seleucid, no day)', () => { - const date = new MesopotamianDate( - { value: '10' }, - { value: '5' }, - { value: '' }, - undefined, - undefined, - true - ) + const date = new MesopotamianDate({ + year: { value: '10' }, + month: { value: '5' }, + day: { value: '' }, + isSeleucidEra: true, + }) expect(date.toString()).toBe( '∅.V.10 SE (ca. 19 August 302 BCE PJC | ca. 14 August 302 BCE PGC)' ) }) it('returns the correct string representation (Seleucid, no month)', () => { - const date = new MesopotamianDate( - { value: '10' }, - { value: '' }, - { value: '12' }, - undefined, - undefined, - true - ) + const date = new MesopotamianDate({ + year: { value: '10' }, + month: { value: '' }, + day: { value: '12' }, + isSeleucidEra: true, + }) expect(date.toString()).toBe( '12.∅.10 SE (ca. 4 May 302 BCE PJC | ca. 29 April 302 BCE PGC)' ) }) it('returns the correct string representation (Seleucid, no year)', () => { - const date = new MesopotamianDate( - { value: '' }, - { value: '5' }, - { value: '12' }, - undefined, - undefined, - true - ) + const date = new MesopotamianDate({ + year: { value: '' }, + month: { value: '5' }, + day: { value: '12' }, + isSeleucidEra: true, + }) expect(date.toString()).toBe('12.V.∅ SE') }) it('returns the correct string representation (Nabonassar era)', () => { - const date = new MesopotamianDate( - { value: '10' }, - { value: '5' }, - { value: '12' }, - nabonassarEraKing, - undefined, - undefined, - false - ) + const date = new MesopotamianDate({ + year: { value: '10' }, + month: { value: '5' }, + day: { value: '12' }, + king: nabonassarEraKing, + isSeleucidEra: false, + }) expect(date.toString()).toBe( '12.V.10 Darius I (11 August 512 BCE PJC | 5 August 512 BCE PGC)' ) }) it('returns the correct string representation (Nabonassar era, no year)', () => { - const date = new MesopotamianDate( - { value: '10' }, - { value: '5' }, - { value: '' }, - nabonassarEraKing, - undefined, - undefined, - false - ) + const date = new MesopotamianDate({ + year: { value: '10' }, + month: { value: '5' }, + day: { value: '' }, + king: nabonassarEraKing, + isSeleucidEra: false, + }) expect(date.toString()).toBe( '∅.V.10 Darius I (ca. 31 July 512 BCE PJC | ca. 25 July 512 BCE PGC)' ) }) it('returns the correct string representation (Nabonassar era, no month)', () => { - const date = new MesopotamianDate( - { value: '10' }, - { value: '' }, - { value: '12' }, - nabonassarEraKing, - undefined, - undefined, - false - ) + const date = new MesopotamianDate({ + year: { value: '10' }, + month: { value: '' }, + day: { value: '12' }, + king: nabonassarEraKing, + isSeleucidEra: false, + }) expect(date.toString()).toBe( '12.∅.10 Darius I (ca. 16 April 512 BCE PJC | ca. 10 April 512 BCE PGC)' ) }) it('returns the correct string representation (Nabonassar era, no day)', () => { - const date = new MesopotamianDate( - { value: '10' }, - { value: '5' }, - { value: '' }, - nabonassarEraKing, - undefined, - undefined, - false - ) + const date = new MesopotamianDate({ + year: { value: '10' }, + month: { value: '5' }, + day: { value: '' }, + king: nabonassarEraKing, + isSeleucidEra: false, + }) expect(date.toString()).toBe( '∅.V.10 Darius I (ca. 31 July 512 BCE PJC | ca. 25 July 512 BCE PGC)' ) }) it('returns the correct string representation (Ur III)', () => { - const date = new MesopotamianDate( - { value: '10' }, - { value: '5' }, - { value: '12' }, - kingUr3, - undefined, - undefined, - false, - Ur3Calendar.UR - ) + const date = new MesopotamianDate({ + year: { value: '10' }, + month: { value: '5' }, + day: { value: '12' }, + king: kingUr3, + ur3Calendar: Ur3Calendar.UR, + }) expect(date.toString()).toBe( '12.V.10 Amar-Suen, Ur calendar (ca. 2035 BCE PJC)' ) }) it('returns the correct string representation (Assyrian date with eponym)', () => { - const date = new MesopotamianDate( - { value: '1' }, - { value: '1' }, - { value: '1' }, - undefined, + const date = new MesopotamianDate({ + year: { value: '1' }, + month: { value: '1' }, + day: { value: '1' }, + isAssyrianDate: true, eponym, - undefined, - true, - undefined - ) + }) expect(date.toString()).toBe( '1.I.1 Adad-nērārī (II) (NA eponym) (ca. 910 BCE PJC)' @@ -247,107 +225,112 @@ describe('MesopotamianDate', () => { }) it('returns the correct string representation (empty)', () => { - const date = new MesopotamianDate( - { value: '' }, - { value: '' }, - { value: '' }, - king - ) + const date = new MesopotamianDate({ + year: { value: '' }, + month: { value: '' }, + day: { value: '' }, + king, + }) expect(date.toString()).toBe('Sargon (ca. 2334–2279 BCE PJC)') }) it('returns the correct string representation (empty, uncertain)', () => { - const date = new MesopotamianDate( - { value: '', isUncertain: true }, - { value: '' }, - { value: '' }, - king - ) + const date = new MesopotamianDate({ + year: { value: '', isUncertain: true }, + month: { value: '' }, + day: { value: '' }, + king, + }) expect(date.toString()).toBe('∅.∅.∅? Sargon (ca. 2334–2279 BCE PJC)') }) it('returns the correct string representation (broken, missing)', () => { - const date = new MesopotamianDate( - { value: '', isBroken: true }, - { value: '', isBroken: true, isIntercalary: true }, - { value: '', isBroken: true }, - king - ) + const date = new MesopotamianDate({ + year: { value: '', isBroken: true }, + month: { value: '', isBroken: true, isIntercalary: true }, + day: { value: '', isBroken: true }, + king, + }) expect(date.toString()).toBe('[x].[x]².[x] Sargon (ca. 2334–2279 BCE PJC)') }) it('returns the correct string representation (broken, reconstructed)', () => { - const date = new MesopotamianDate( - { value: '1', isBroken: true }, - { value: '2', isBroken: true, isIntercalary: true }, - { value: '3', isBroken: true }, - king - ) + const date = new MesopotamianDate({ + year: { value: '1', isBroken: true }, + month: { value: '2', isBroken: true, isIntercalary: true }, + day: { value: '3', isBroken: true }, + king, + }) expect(date.toString()).toBe('[3].[II²].[1] Sargon (ca. 2334 BCE PJC)') }) it('returns the correct string representation (uncertain)', () => { - const date = new MesopotamianDate( - { value: '1', isUncertain: true }, - { value: '2', isUncertain: true, isIntercalary: true }, - { value: '3', isUncertain: true }, - king - ) + const date = new MesopotamianDate({ + year: { value: '1', isUncertain: true }, + month: { value: '2', isUncertain: true, isIntercalary: true }, + day: { value: '3', isUncertain: true }, + king, + }) expect(date.toString()).toBe('3?.II²?.1? Sargon (ca. 2334 BCE PJC)') }) it('returns the correct string representation (broken and uncertain)', () => { - const date = new MesopotamianDate( - { value: '1', isBroken: true, isUncertain: true }, - { value: '2', isBroken: true, isUncertain: true, isIntercalary: true }, - { value: '3', isBroken: true, isUncertain: true }, - king - ) + const date = new MesopotamianDate({ + year: { value: '1', isBroken: true, isUncertain: true }, + month: { + value: '2', + isBroken: true, + isUncertain: true, + isIntercalary: true, + }, + day: { value: '3', isBroken: true, isUncertain: true }, + king, + }) expect(date.toString()).toBe('[3]?.[II²]?.[1]? Sargon (ca. 2334 BCE PJC)') }) describe('toJulianDate branching', () => { it('returns empty when none of the conditions are met', () => { - const date = new MesopotamianDate( - { value: '1' }, - { value: '1' }, - { value: '1' } - ) + const date = new MesopotamianDate({ + year: { value: '1' }, + month: { value: '1' }, + day: { value: '1' }, + }) expect(date.toModernDate()).toBe('') }) it('returns the correct modern date for a king without orderGlobal', () => { const unorderedKing = { ...king, orderGlobal: -1 } - const date = new MesopotamianDate( - { value: '10' }, - { value: '5' }, - { value: '12' }, - unorderedKing - ) + const date = new MesopotamianDate({ + year: { value: '10' }, + month: { value: '5' }, + day: { value: '12' }, + king: unorderedKing, + }) expect(date.toModernDate()).toBe('ca. 2325 BCE PJC') }) }) it('handles king with orderGlobal matching rulerToBrinkmanKings', () => { const kingWithSpecificOrder = { ...king, orderGlobal: 1 } - const date = new MesopotamianDate( - { value: '1' }, - { value: '1' }, - { value: '1' }, - kingWithSpecificOrder - ) + const date = new MesopotamianDate({ + year: { value: '1' }, + month: { value: '1' }, + day: { value: '1' }, + king: kingWithSpecificOrder, + }) const result = date.toModernDate() expect(result).toBe('ca. 2334 BCE PJC') }) it('handles king without a date', () => { const kingWithoutDate = { ...king, date: '' } - const date = new MesopotamianDate( - { value: '1' }, - { value: '1' }, - { value: '1' }, - kingWithoutDate - ) + const date = new MesopotamianDate({ + year: { value: '1' }, + month: { value: '1' }, + day: { value: '1' }, + king: kingWithoutDate, + }) expect(date.toModernDate()).toBe('') }) }) diff --git a/src/chronology/domain/Date.ts b/src/chronology/domain/Date.ts index 9201ea4d1..cbadae22b 100644 --- a/src/chronology/domain/Date.ts +++ b/src/chronology/domain/Date.ts @@ -5,26 +5,7 @@ import { MesopotamianDateBase } from 'chronology/domain/DateBase' export class MesopotamianDate extends MesopotamianDateBase { static fromJson(dateJson: MesopotamianDateDto): MesopotamianDate { - const { - year, - month, - day, - eponym, - king, - isSeleucidEra, - isAssyrianDate, - ur3Calendar, - } = dateJson - return new MesopotamianDate( - year, - month, - day, - king, - eponym, - isSeleucidEra, - isAssyrianDate, - ur3Calendar - ) + return new MesopotamianDate({ ...dateJson }) } toString(): string { diff --git a/src/chronology/domain/DateBase.ts b/src/chronology/domain/DateBase.ts index 47261a9fd..914608108 100644 --- a/src/chronology/domain/DateBase.ts +++ b/src/chronology/domain/DateBase.ts @@ -55,16 +55,25 @@ export class MesopotamianDateBase { isAssyrianDate?: boolean ur3Calendar?: Ur3Calendar - constructor( - year: DateField, - month: MonthField, - day: DateField, - king?: KingDateField, - eponym?: EponymDateField, - isSeleucidEra?: boolean, - isAssyrianDate?: boolean, + constructor({ + year, + month, + day, + king, + eponym, + isSeleucidEra, + isAssyrianDate, + ur3Calendar, + }: { + year: DateField + month: MonthField + day: DateField + king?: KingDateField + eponym?: EponymDateField + isSeleucidEra?: boolean + isAssyrianDate?: boolean ur3Calendar?: Ur3Calendar - ) { + }) { this.year = year this.month = month this.day = day @@ -143,6 +152,11 @@ export class MesopotamianDateBase { const year = parseInt(this.year.value) const month = parseInt(this.month.value) const day = parseInt(this.day.value) + // ToDo: Change this to ranges + // Implement `getDateRangeFromPartialDate` + // And use it. + // If possible, try to adjust to exact ranges + // that differ from scenario to scenario return { year: isNaN(year) ? -1 : year, month: isNaN(month) ? 1 : month, diff --git a/src/chronology/domain/DateRange.ts b/src/chronology/domain/DateRange.ts new file mode 100644 index 000000000..454a6a8f6 --- /dev/null +++ b/src/chronology/domain/DateRange.ts @@ -0,0 +1,28 @@ +import { MesopotamianDate } from 'chronology/domain/Date' + +export function getDateRangeFromPartialDate(date: MesopotamianDate): DateRange { + // ToDo: + // Use ranges when calculating approximation. + const startDate = new MesopotamianDate({ ...date }) + const endDate = new MesopotamianDate({ ...date }) + return new DateRange({ start: startDate, end: endDate }) +} + +export default class DateRange { + start: MesopotamianDate + end: MesopotamianDate + constructor({ + start, + end, + }: { + start: MesopotamianDate + end: MesopotamianDate + }) { + this.start = start + this.end = end + } + + toString(): string { + return `${this.start.toString()} - ${this.start.toString()}` + } +} diff --git a/src/chronology/ui/DateEditor/DatesInTextSelection.test.tsx b/src/chronology/ui/DateEditor/DatesInTextSelection.test.tsx index ba13c69fa..790f42eb1 100644 --- a/src/chronology/ui/DateEditor/DatesInTextSelection.test.tsx +++ b/src/chronology/ui/DateEditor/DatesInTextSelection.test.tsx @@ -116,7 +116,6 @@ describe('DatesInTextSelection', () => { ) - expect(screen.queryByLabelText('Add date button')).not.toBeInTheDocument() }) }) diff --git a/src/test-support/date-fixtures.ts b/src/test-support/date-fixtures.ts index d63fdf8a7..5ee72a090 100644 --- a/src/test-support/date-fixtures.ts +++ b/src/test-support/date-fixtures.ts @@ -23,15 +23,15 @@ export const mesopotamianDateFactory = Factory.define(() => { ? chance.pickone(Object.values(Ur3Calendar)) : undefined - return new MesopotamianDate( + return new MesopotamianDate({ year, - { + month: { value: chance.integer({ min: 1, max: 12 }).toString(), isBroken: chance.bool(), isUncertain: chance.bool(), isIntercalary: chance.bool(), }, - { + day: { value: chance.integer({ min: 1, max: 29 }).toString(), isBroken: chance.bool(), isUncertain: chance.bool(), @@ -40,6 +40,6 @@ export const mesopotamianDateFactory = Factory.define(() => { eponym, isSeleucidEra, isAssyrianDate, - ur3Calendar - ) + ur3Calendar, + }) }) diff --git a/src/test-support/fragment-fixtures.ts b/src/test-support/fragment-fixtures.ts index 00cdd31f4..530f9315c 100644 --- a/src/test-support/fragment-fixtures.ts +++ b/src/test-support/fragment-fixtures.ts @@ -302,14 +302,12 @@ export const fragmentFactory = Factory.define( associations.projects ?? [], associations.date ?? - new MesopotamianDate( - { value: '1' }, - { value: '1' }, - { value: '1' }, - undefined, - undefined, - true - ), + new MesopotamianDate({ + year: { value: '1' }, + month: { value: '1' }, + day: { value: '1' }, + isSeleucidEra: true, + }), associations.datesInText ?? undefined, associations.archaeology ?? archaeologyFactory.build({}, { transient: { chance } }) diff --git a/src/test-support/test-fragment.ts b/src/test-support/test-fragment.ts index 999994f58..78cd57bf6 100644 --- a/src/test-support/test-fragment.ts +++ b/src/test-support/test-fragment.ts @@ -516,22 +516,18 @@ export const fragment = new Fragment( }, externalNumbers, [], - new MesopotamianDate( - { value: '1' }, - { value: '1' }, - { value: '1' }, - undefined, - undefined, - true - ), + new MesopotamianDate({ + year: { value: '1' }, + month: { value: '1' }, + day: { value: '1' }, + isSeleucidEra: true, + }), [ - new MesopotamianDate( - { value: '1' }, - { value: '1' }, - { value: '1' }, - undefined, - undefined, - true - ), + new MesopotamianDate({ + year: { value: '1' }, + month: { value: '1' }, + day: { value: '1' }, + isSeleucidEra: true, + }), ] ) From 65b2541063c2f198c13241ee00d059623bd1f4b2 Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Wed, 28 Feb 2024 21:00:19 +0000 Subject: [PATCH 87/91] Implement date ranges & conversion (WiP) --- src/chronology/domain/Date.ts | 128 +---------------- src/chronology/domain/DateBase.ts | 112 ++++++++++----- src/chronology/domain/DateRange.ts | 211 ++++++++++++++++++++++++---- src/chronology/domain/DateString.ts | 127 +++++++++++++++++ 4 files changed, 390 insertions(+), 188 deletions(-) create mode 100644 src/chronology/domain/DateString.ts diff --git a/src/chronology/domain/Date.ts b/src/chronology/domain/Date.ts index cbadae22b..070948031 100644 --- a/src/chronology/domain/Date.ts +++ b/src/chronology/domain/Date.ts @@ -1,132 +1,8 @@ import { MesopotamianDateDto } from 'fragmentarium/domain/FragmentDtos' -import _ from 'lodash' -import { romanize } from 'romans' -import { MesopotamianDateBase } from 'chronology/domain/DateBase' +import { MesopotamianDateString } from 'chronology/domain/DateString' -export class MesopotamianDate extends MesopotamianDateBase { +export class MesopotamianDate extends MesopotamianDateString { static fromJson(dateJson: MesopotamianDateDto): MesopotamianDate { return new MesopotamianDate({ ...dateJson }) } - - toString(): string { - const dayMonthYear = this.dayMonthYearToString().join('.') - const dateTail = `${this.kingEponymOrEraToString()}${this.ur3CalendarToString()}${this.modernDateToString()}` - return [dayMonthYear, dateTail] - .filter((string) => !_.isEmpty(string)) - .join(' ') - } - - private modernDateToString(): string { - const julianDate = this.toModernDate('Julian') - const gregorianDate = this.toModernDate('Gregorian') - return julianDate && - gregorianDate && - gregorianDate.replace('PGC', 'PJC') !== julianDate - ? ` (${[julianDate, gregorianDate].join(' | ')})` - : julianDate - ? ` (${julianDate})` - : '' - } - - private dayMonthYearToString(): string[] { - const fields = ['day', 'month', 'year'] - const emptyParams = fields.map((field) => { - const { isBroken, isUncertain, value } = this[field] - return !isBroken && !isUncertain && _.isEmpty(value) - }) - if (!emptyParams.includes(false)) { - return [] - } - return fields.map((field) => - this.datePartToString(field as 'year' | 'day' | 'month') - ) - } - - private parameterToString( - field: 'year' | 'day' | 'month', - element?: string - ): string { - element = - !_.isEmpty(element) && typeof element == 'string' - ? element - : !_.isEmpty(this[field].value) - ? this[field].value - : '∅' - return this.brokenAndUncertainToString(field, element) - } - - private brokenAndUncertainToString( - field: 'year' | 'day' | 'month', - element: string - ): string { - const { isBroken, isUncertain, value } = this[field] - let brokenIntercalary = '' - if (isBroken && !value) { - element = 'x' - brokenIntercalary = - field === 'month' && this.month.isIntercalary ? '²' : '' - } - return this.getBrokenAndUncertainString({ - element, - brokenIntercalary, - isBroken, - isUncertain, - }) - } - - private getBrokenAndUncertainString({ - element, - brokenIntercalary = '', - isBroken, - isUncertain, - }: { - element: string - brokenIntercalary?: string - isBroken?: boolean - isUncertain?: boolean - }): string { - return `${isBroken ? '[' : ''}${element}${ - isBroken ? ']' + brokenIntercalary : '' - }${isUncertain ? '?' : ''}` - } - - datePartToString(part: 'year' | 'month' | 'day'): string { - if (part === 'month') { - const month = Number(this.month.value) - ? romanize(Number(this.month.value)) - : this.month.value - const intercalary = this.month.isIntercalary ? '²' : '' - return this.parameterToString('month', month + intercalary) - } - return this.parameterToString(part) - } - - private eponymToString(): string { - return `${this.getBrokenAndUncertainString({ - element: this?.eponym?.name ?? '', - ...this?.eponym, - })} (${this?.eponym?.phase} eponym)` - } - - private kingToString(): string { - return this.getBrokenAndUncertainString({ - element: this.king?.name ?? '', - ...this?.king, - }) - } - - kingEponymOrEraToString(): string { - if (this.isSeleucidEra) { - return 'SE' - } else if (this.isAssyrianDate && this.eponym?.name) { - return this.eponymToString() - } else if (this.king?.name) { - return this.kingToString() - } - return '' - } - - ur3CalendarToString(): string { - return this.ur3Calendar ? `, ${this.ur3Calendar} calendar` : '' - } } diff --git a/src/chronology/domain/DateBase.ts b/src/chronology/domain/DateBase.ts index 914608108..3fe9279bd 100644 --- a/src/chronology/domain/DateBase.ts +++ b/src/chronology/domain/DateBase.ts @@ -3,6 +3,7 @@ import { Eponym } from 'chronology/ui/DateEditor/Eponyms' import DateConverter from 'chronology/domain/DateConverter' import data from 'chronology/domain/dateConverterData.json' import _ from 'lodash' +import DateRange from './DateRange' export interface DateField { value: string @@ -32,6 +33,13 @@ interface DateProps { calendar: 'Julian' | 'Gregorian' } +export enum DateType { + seleucidDate = 'seleucidDate', + nabonassarEraDate = 'nabonassarEraDate', + assyrianDate = 'assyrianDate', + kingDate = 'kingDate', +} + export enum Ur3Calendar { ADAB = 'Adab', GIRSU = 'Girsu', @@ -54,6 +62,7 @@ export class MesopotamianDateBase { isSeleucidEra?: boolean isAssyrianDate?: boolean ur3Calendar?: Ur3Calendar + range?: DateRange constructor({ year, @@ -82,10 +91,15 @@ export class MesopotamianDateBase { this.isSeleucidEra = isSeleucidEra this.isAssyrianDate = isAssyrianDate this.ur3Calendar = ur3Calendar + if (this.getEmptyOrBrokenFields().length > 0 && this.getType() !== null) { + this.range = DateRange.getRangeFromPartialDate(this) + console.log('!! Range:', this.range, this.range.toDateString()) + } } - private isSeleucidEraApplicable(year: number): boolean { - return !!this.isSeleucidEra && year > 0 + private isSeleucidEraApplicable(year?: number | string): boolean { + year = typeof year === 'number' ? year : parseInt(year ?? '') + return !!this.isSeleucidEra && !isNaN(year) && year > 0 } private isNabonassarEraApplicable(): boolean { @@ -103,44 +117,48 @@ export class MesopotamianDateBase { return !!this.king?.date } - toModernDate(calendar: 'Julian' | 'Gregorian' = 'Julian'): string { - const dateProps = { - ...this.getDateApproximation(), - calendar, - } - let julianDate = '' - if (this.isSeleucidEraApplicable(dateProps.year)) { - julianDate = this.seleucidToModernDate(dateProps) + getType(): DateType | null { + if (this?.year?.value && this.isSeleucidEraApplicable(this?.year?.value)) { + return DateType.seleucidDate } else if (this.isNabonassarEraApplicable()) { - julianDate = this.getNabonassarEraDate(dateProps) + return DateType.nabonassarEraDate } else if (this.isAssyrianDateApplicable()) { - julianDate = this.getAssyrianDate({ calendar: 'Julian' }) + return DateType.assyrianDate } else if (this.isKingDateApplicable()) { - julianDate = this.kingToModernDate({ ...dateProps, calendar: 'Julian' }) + return DateType.kingDate } - return julianDate + return null } - private getNabonassarEraDate({ - year, - month, - day, - isApproximate, - calendar, - }: DateProps): string { - return this.nabonassarEraToModernDate({ - year: year > 0 ? year : 1, - month, - day, - isApproximate, + toModernDate(calendar: 'Julian' | 'Gregorian' = 'Julian'): string { + const type = this.getType() + if (type === null) { + return '' + } + const dateProps = { + ...this.getDateApproximation(), calendar, - }) + } + const { year } = dateProps + return { + seleucidDate: () => this.seleucidToModernDate(dateProps), + nabonassarEraDate: () => + this.nabonassarEraToModernDate({ + ...dateProps, + year: year > 0 ? year : 1, + }), + assyrianDate: () => this.getAssyrianDate({ calendar: 'Julian' }), + kingDate: () => + this.kingToModernDate({ ...dateProps, calendar: 'Julian' }), + }[type]() } private getAssyrianDate({ calendar = 'Julian', }: Pick): string { return `ca. ${this.eponym?.date} BCE ${calendarToAbbreviation(calendar)}` + // ToDo: Continue here + // Calculate years in range if year is missing } private getDateApproximation(): { @@ -152,19 +170,28 @@ export class MesopotamianDateBase { const year = parseInt(this.year.value) const month = parseInt(this.month.value) const day = parseInt(this.day.value) - // ToDo: Change this to ranges - // Implement `getDateRangeFromPartialDate` - // And use it. - // If possible, try to adjust to exact ranges - // that differ from scenario to scenario + const isApproximate = this.isApproximate() + // ToDo: Change this return { year: isNaN(year) ? -1 : year, month: isNaN(month) ? 1 : month, day: isNaN(day) ? 1 : day, - isApproximate: this.isApproximate(), + isApproximate, } } + getEmptyOrBrokenFields(): Array<'year' | 'month' | 'day'> { + const fields: Array<'year' | 'month' | 'day'> = ['year', 'month', 'day'] + return fields + .map((field) => { + if (isNaN(parseInt(this[field].value)) || this[field].isBroken) { + return field + } + return null + }) + .filter((field) => !!field) as Array<'year' | 'month' | 'day'> + } + private isApproximate(): boolean { return [ _.some( @@ -193,6 +220,8 @@ export class MesopotamianDateBase { isApproximate, calendar, }: DateProps): string { + // ToDo: Continue here + // Use converter to compute earliest and latest dates in range const converter = new DateConverter() converter.setToSeBabylonianDate(year, month, day) return this.insertDateApproximation( @@ -208,12 +237,11 @@ export class MesopotamianDateBase { isApproximate, calendar, }: DateProps): string { - const kingName = Object.keys(data.rulerToBrinkmanKings).find( - (key) => data.rulerToBrinkmanKings[key] === this.king?.orderGlobal - ) - if (kingName) { + if (this.kingName) { + // ToDo: Continue here + // Use converter to compute earliest and latest dates in range const converter = new DateConverter() - converter.setToMesopotamianDate(kingName, year, month, day) + converter.setToMesopotamianDate(this.kingName, year, month, day) return this.insertDateApproximation( converter.toDateString(calendar), isApproximate @@ -222,6 +250,12 @@ export class MesopotamianDateBase { return '' } + get kingName(): string | undefined { + return Object.keys(data.rulerToBrinkmanKings).find( + (key) => data.rulerToBrinkmanKings[key] === this.king?.orderGlobal + ) + } + private kingToModernDate({ year, calendar = 'Julian', @@ -234,6 +268,8 @@ export class MesopotamianDateBase { : this.king?.date && !['', '?'].includes(this.king?.date) ? `ca. ${this.king?.date} BCE ${calendarToAbbreviation(calendar)}` : '' + // ToDo: Continue here + // Calculate years in range if year is missing } private insertDateApproximation( diff --git a/src/chronology/domain/DateRange.ts b/src/chronology/domain/DateRange.ts index 454a6a8f6..bc83175d5 100644 --- a/src/chronology/domain/DateRange.ts +++ b/src/chronology/domain/DateRange.ts @@ -1,28 +1,191 @@ -import { MesopotamianDate } from 'chronology/domain/Date' - -export function getDateRangeFromPartialDate(date: MesopotamianDate): DateRange { - // ToDo: - // Use ranges when calculating approximation. - const startDate = new MesopotamianDate({ ...date }) - const endDate = new MesopotamianDate({ ...date }) - return new DateRange({ start: startDate, end: endDate }) -} +import { DateType, MesopotamianDateBase } from 'chronology/domain/DateBase' +import DateConverter from './DateConverter' +import { CalendarProps } from './DateConverterBase' export default class DateRange { - start: MesopotamianDate - end: MesopotamianDate - constructor({ - start, - end, - }: { - start: MesopotamianDate - end: MesopotamianDate - }) { - this.start = start - this.end = end - } - - toString(): string { - return `${this.start.toString()} - ${this.start.toString()}` + start: CalendarProps + end: CalendarProps + private _converter: DateConverter + + constructor() { + this._converter = new DateConverter() + this.start = this._converter.calendar + this.end = this._converter.calendar + } + + toDateString(calendarType?: 'Julian' | 'Gregorian'): string { + this._converter.setToCjdn(this.start.cjdn) + const startDateString = this._converter.toDateString(calendarType) + this._converter.setToCjdn(this.end.cjdn) + const endDateString = this._converter.toDateString(calendarType) + const endDateArray = endDateString.split(' ').reverse() + const startDateArray: string[] = [] + for (const [index, startElement] of startDateString + .split(' ') + .reverse() + .entries()) { + const endElement = endDateArray[index] + if (startElement !== endElement) { + startDateArray.push(startElement) + } + } + // ToDo: Continue here. Verify that it works as expected + return `${startDateArray.reverse().join(' ')} - ${endDateString}` + } + + private setToPartialDate(date: MesopotamianDateBase): void { + const fieldsToUpdate = date.getEmptyOrBrokenFields() + const defaultValues = this.getDefaultDateValues(date) + + const startDate = this.calculateDateValues( + fieldsToUpdate, + defaultValues, + 'start', + date + ) + const endDate = this.calculateDateValues( + fieldsToUpdate, + defaultValues, + 'end', + date + ) + + this.setDateBasedOnType(date, startDate, 'start') + this.setDateBasedOnType(date, endDate, 'end') + } + + private getDefaultDateValues( + date: MesopotamianDateBase + ): { year: number; month: number; day: number } { + const parseValue = (value: { value: string }) => parseInt(value.value) + return { + year: parseValue(date.year), + month: parseValue(date.month), + day: parseValue(date.day), + } + } + + private calculateDateValues( + fields: Array<'year' | 'month' | 'day'>, + defaultValues: { year: number; month: number; day: number }, + type: 'start' | 'end', + date: MesopotamianDateBase + ): { year: number; month: number; day: number } { + return fields.reduce( + (acc, field) => ({ + ...acc, + [field]: + type === 'start' + ? 1 + : parseInt(this.getEndValueForPartialDate(date, field)), + }), + defaultValues + ) + } + + private setDateBasedOnType( + date: MesopotamianDateBase, + dateValues: { year: number; month: number; day: number }, + type: 'start' | 'end' + ): void { + if (date.getType() === DateType.seleucidDate) { + this._converter.setToSeBabylonianDate( + dateValues.year, + dateValues.month, + dateValues.day + ) + } else if (date.getType() === DateType.nabonassarEraDate) { + this._converter.setToMesopotamianDate( + date.kingName as string, + dateValues.year, + dateValues.month, + dateValues.day + ) + } + + this[type] = { ...this._converter.calendar } + } + + private getEndValueForPartialDate( + date: MesopotamianDateBase, + field: 'year' | 'month' | 'day' + ): string { + const dateType = date.getType() + if (dateType === DateType.seleucidDate) { + return { + year: () => `${this.seleucidRangeEndYear}`, + month: () => `${this.getSeleucidDateEndMonth(date)}`, + day: () => `${this.getSeleucidDateEndDay(date)}`, + }[field]() + } else if (DateType.nabonassarEraDate) { + return { + year: () => `${this.getNabonassarRangeEndYear}`, + month: () => `${this.getNabonassarDateEndMonth(date)}`, + day: () => `${this.getNabonassarDateEndDay(date)}`, + }[field]() + } + return '' + } + + private get seleucidRangeEndYear(): number { + return this._converter.latestDate.seBabylonianYear + } + + private getSeleucidRangeEndYear(date: MesopotamianDateBase): number { + return date.getEmptyOrBrokenFields().includes('year') + ? this.seleucidRangeEndYear + : parseInt(date.year.value) + } + + private getSeleucidDateEndMonth(date: MesopotamianDateBase): number { + const year = this.getSeleucidRangeEndYear(date) + return date.getEmptyOrBrokenFields().includes('month') + ? this._converter.getMesopotamianMonthsOfSeYear(year).length + : parseInt(date.month.value) + } + + private getSeleucidDateEndDay(date: MesopotamianDateBase): number { + const year = this.getSeleucidRangeEndYear(date) + const month = this.getSeleucidDateEndMonth(date) + this._converter.setToSeBabylonianDate(year, month, 1) + return this._converter.calendar.mesopotamianMonthLength ?? 29 + } + + private get nabonassarRangeEndYear(): number { + return this._converter.latestDate.regnalYears ?? 1 + } + + private getNabonassarRangeEndYear(date: MesopotamianDateBase): number { + return date.getEmptyOrBrokenFields().includes('year') + ? this.nabonassarRangeEndYear + : parseInt(date.year.value) + } + + private getNabonassarDateEndMonth(date: MesopotamianDateBase): number { + const year = this.getNabonassarRangeEndYear(date) + this._converter.setToMesopotamianDate(date.kingName as string, year, 1, 1) + return date.getEmptyOrBrokenFields().includes('month') + ? this._converter.getMesopotamianMonthsOfSeYear( + this._converter.calendar.seBabylonianYear + ).length + : parseInt(date.month.value) + } + + private getNabonassarDateEndDay(date: MesopotamianDateBase): number { + const year = this.getNabonassarRangeEndYear(date) + const month = this.getNabonassarDateEndMonth(date) + this._converter.setToMesopotamianDate( + date.kingName as string, + year, + month, + 1 + ) + return this._converter.calendar.mesopotamianMonthLength ?? 29 + } + + static getRangeFromPartialDate(date: MesopotamianDateBase): DateRange { + const range = new DateRange() + range.setToPartialDate(date) + return range } } diff --git a/src/chronology/domain/DateString.ts b/src/chronology/domain/DateString.ts new file mode 100644 index 000000000..6c338c354 --- /dev/null +++ b/src/chronology/domain/DateString.ts @@ -0,0 +1,127 @@ +import _ from 'lodash' +import { romanize } from 'romans' +import { MesopotamianDateBase } from 'chronology/domain/DateBase' + +export class MesopotamianDateString extends MesopotamianDateBase { + toString(): string { + const dayMonthYear = this.dayMonthYearToString().join('.') + const dateTail = `${this.kingEponymOrEraToString()}${this.ur3CalendarToString()}${this.modernDateToString()}` + return [dayMonthYear, dateTail] + .filter((string) => !_.isEmpty(string)) + .join(' ') + } + + private modernDateToString(): string { + const julianDate = this.toModernDate('Julian') + const gregorianDate = this.toModernDate('Gregorian') + return julianDate && + gregorianDate && + gregorianDate.replace('PGC', 'PJC') !== julianDate + ? ` (${[julianDate, gregorianDate].join(' | ')})` + : julianDate + ? ` (${julianDate})` + : '' + } + + private dayMonthYearToString(): string[] { + const fields = ['day', 'month', 'year'] + const emptyParams = fields.map((field) => { + const { isBroken, isUncertain, value } = this[field] + return !isBroken && !isUncertain && _.isEmpty(value) + }) + if (!emptyParams.includes(false)) { + return [] + } + return fields.map((field) => + this.datePartToString(field as 'year' | 'day' | 'month') + ) + } + + private parameterToString( + field: 'year' | 'day' | 'month', + element?: string + ): string { + element = + !_.isEmpty(element) && typeof element == 'string' + ? element + : !_.isEmpty(this[field].value) + ? this[field].value + : '∅' + return this.brokenAndUncertainToString(field, element) + } + + private brokenAndUncertainToString( + field: 'year' | 'day' | 'month', + element: string + ): string { + const { isBroken, isUncertain, value } = this[field] + let brokenIntercalary = '' + if (isBroken && !value) { + element = 'x' + brokenIntercalary = + field === 'month' && this.month.isIntercalary ? '²' : '' + } + return this.getBrokenAndUncertainString({ + element, + brokenIntercalary, + isBroken, + isUncertain, + }) + } + + private getBrokenAndUncertainString({ + element, + brokenIntercalary = '', + isBroken, + isUncertain, + }: { + element: string + brokenIntercalary?: string + isBroken?: boolean + isUncertain?: boolean + }): string { + return `${isBroken ? '[' : ''}${element}${ + isBroken ? ']' + brokenIntercalary : '' + }${isUncertain ? '?' : ''}` + } + + datePartToString(part: 'year' | 'month' | 'day'): string { + if (part === 'month') { + const month = Number(this.month.value) + ? romanize(Number(this.month.value)) + : this.month.value + const intercalary = this.month.isIntercalary ? '²' : '' + return this.parameterToString('month', month + intercalary) + } + return this.parameterToString(part) + } + + private eponymToString(): string { + return `${this.getBrokenAndUncertainString({ + element: this?.eponym?.name ?? '', + ...this?.eponym, + })} (${this?.eponym?.phase} eponym)` + } + + private kingToString(): string { + return this.getBrokenAndUncertainString({ + element: this.king?.name ?? '', + ...this?.king, + }) + } + + kingEponymOrEraToString(): string { + if (this.isSeleucidEra) { + return 'SE' + } else if (this.isAssyrianDate && this.eponym?.name) { + return this.eponymToString() + } else if (this.king?.name) { + return this.kingToString() + } + return '' + } + + ur3CalendarToString(): string { + return this.ur3Calendar ? `, ${this.ur3Calendar} calendar` : '' + } +} From 1b4e9ec723ced9ab50ed784dae84bf286a92905d Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Mon, 4 Mar 2024 14:35:53 +0000 Subject: [PATCH 88/91] Finalize ranges & update tests --- src/chronology/domain/Date.test.ts | 10 ++--- src/chronology/domain/DateBase.ts | 65 +++++++++++++++++------------- src/chronology/domain/DateRange.ts | 61 +++++++++++++++------------- 3 files changed, 74 insertions(+), 62 deletions(-) diff --git a/src/chronology/domain/Date.test.ts b/src/chronology/domain/Date.test.ts index de1284aaf..75099ccef 100644 --- a/src/chronology/domain/Date.test.ts +++ b/src/chronology/domain/Date.test.ts @@ -119,7 +119,7 @@ describe('MesopotamianDate', () => { isSeleucidEra: true, }) expect(date.toString()).toBe( - '∅.V.10 SE (ca. 19 August 302 BCE PJC | ca. 14 August 302 BCE PGC)' + '∅.V.10 SE (ca. 19 August - 16 September 302 BCE PJC | ca. 14 August - 11 September 302 BCE PGC)' ) }) @@ -131,7 +131,7 @@ describe('MesopotamianDate', () => { isSeleucidEra: true, }) expect(date.toString()).toBe( - '12.∅.10 SE (ca. 4 May 302 BCE PJC | ca. 29 April 302 BCE PGC)' + '12.∅.10 SE (ca. 4 May 302 - 24 March 301 BCE PJC | ca. 29 April 302 - 20 March 301 BCE PGC)' ) }) @@ -167,7 +167,7 @@ describe('MesopotamianDate', () => { isSeleucidEra: false, }) expect(date.toString()).toBe( - '∅.V.10 Darius I (ca. 31 July 512 BCE PJC | ca. 25 July 512 BCE PGC)' + '∅.V.10 Darius I (ca. 31 July - 29 August 512 BCE PJC | ca. 25 July - 23 August 512 BCE PGC)' ) }) @@ -180,7 +180,7 @@ describe('MesopotamianDate', () => { isSeleucidEra: false, }) expect(date.toString()).toBe( - '12.∅.10 Darius I (ca. 16 April 512 BCE PJC | ca. 10 April 512 BCE PGC)' + '12.∅.10 Darius I (ca. 16 April 512 - 6 March 511 BCE PJC | ca. 10 April 512 - 28 February 511 BCE PGC)' ) }) @@ -193,7 +193,7 @@ describe('MesopotamianDate', () => { isSeleucidEra: false, }) expect(date.toString()).toBe( - '∅.V.10 Darius I (ca. 31 July 512 BCE PJC | ca. 25 July 512 BCE PGC)' + '∅.V.10 Darius I (ca. 31 July - 29 August 512 BCE PJC | ca. 25 July - 23 August 512 BCE PGC)' ) }) diff --git a/src/chronology/domain/DateBase.ts b/src/chronology/domain/DateBase.ts index 3fe9279bd..c39efc3cc 100644 --- a/src/chronology/domain/DateBase.ts +++ b/src/chronology/domain/DateBase.ts @@ -91,9 +91,13 @@ export class MesopotamianDateBase { this.isSeleucidEra = isSeleucidEra this.isAssyrianDate = isAssyrianDate this.ur3Calendar = ur3Calendar - if (this.getEmptyOrBrokenFields().length > 0 && this.getType() !== null) { + if ( + this.getEmptyFields().length > 0 && + [DateType.nabonassarEraDate, DateType.seleucidDate].includes( + this.dateType as DateType + ) + ) { this.range = DateRange.getRangeFromPartialDate(this) - console.log('!! Range:', this.range, this.range.toDateString()) } } @@ -117,7 +121,7 @@ export class MesopotamianDateBase { return !!this.king?.date } - getType(): DateType | null { + get dateType(): DateType | null { if (this?.year?.value && this.isSeleucidEraApplicable(this?.year?.value)) { return DateType.seleucidDate } else if (this.isNabonassarEraApplicable()) { @@ -131,14 +135,11 @@ export class MesopotamianDateBase { } toModernDate(calendar: 'Julian' | 'Gregorian' = 'Julian'): string { - const type = this.getType() + const type = this.dateType if (type === null) { return '' } - const dateProps = { - ...this.getDateApproximation(), - calendar, - } + const dateProps = this.getDateProps(calendar) const { year } = dateProps return { seleucidDate: () => this.seleucidToModernDate(dateProps), @@ -157,34 +158,31 @@ export class MesopotamianDateBase { calendar = 'Julian', }: Pick): string { return `ca. ${this.eponym?.date} BCE ${calendarToAbbreviation(calendar)}` - // ToDo: Continue here - // Calculate years in range if year is missing } - private getDateApproximation(): { + private getDateProps( + calendar: 'Julian' | 'Gregorian' = 'Julian' + ): { year: number month: number day: number isApproximate: boolean + calendar: 'Julian' | 'Gregorian' } { - const year = parseInt(this.year.value) - const month = parseInt(this.month.value) - const day = parseInt(this.day.value) - const isApproximate = this.isApproximate() - // ToDo: Change this return { - year: isNaN(year) ? -1 : year, - month: isNaN(month) ? 1 : month, - day: isNaN(day) ? 1 : day, - isApproximate, + year: parseInt(this.year.value) ?? -1, + month: parseInt(this.month.value) ?? 1, + day: parseInt(this.day.value) ?? 1, + isApproximate: this.isApproximate(), + calendar, } } - getEmptyOrBrokenFields(): Array<'year' | 'month' | 'day'> { + getEmptyFields(): Array<'year' | 'month' | 'day'> { const fields: Array<'year' | 'month' | 'day'> = ['year', 'month', 'day'] return fields .map((field) => { - if (isNaN(parseInt(this[field].value)) || this[field].isBroken) { + if (isNaN(parseInt(this[field].value))) { return field } return null @@ -220,8 +218,10 @@ export class MesopotamianDateBase { isApproximate, calendar, }: DateProps): string { - // ToDo: Continue here - // Use converter to compute earliest and latest dates in range + const dateRangeString = this.getDateRangeString(calendar) + if (dateRangeString) { + return dateRangeString + } const converter = new DateConverter() converter.setToSeBabylonianDate(year, month, day) return this.insertDateApproximation( @@ -238,8 +238,10 @@ export class MesopotamianDateBase { calendar, }: DateProps): string { if (this.kingName) { - // ToDo: Continue here - // Use converter to compute earliest and latest dates in range + const dateRangeString = this.getDateRangeString(calendar) + if (dateRangeString) { + return dateRangeString + } const converter = new DateConverter() converter.setToMesopotamianDate(this.kingName, year, month, day) return this.insertDateApproximation( @@ -250,6 +252,15 @@ export class MesopotamianDateBase { return '' } + getDateRangeString(calendar: 'Julian' | 'Gregorian'): string | undefined { + if (this.range !== undefined) { + return this.insertDateApproximation( + this.range.toDateString(calendar), + true + ) + } + } + get kingName(): string | undefined { return Object.keys(data.rulerToBrinkmanKings).find( (key) => data.rulerToBrinkmanKings[key] === this.king?.orderGlobal @@ -268,8 +279,6 @@ export class MesopotamianDateBase { : this.king?.date && !['', '?'].includes(this.king?.date) ? `ca. ${this.king?.date} BCE ${calendarToAbbreviation(calendar)}` : '' - // ToDo: Continue here - // Calculate years in range if year is missing } private insertDateApproximation( diff --git a/src/chronology/domain/DateRange.ts b/src/chronology/domain/DateRange.ts index bc83175d5..c0073c6f1 100644 --- a/src/chronology/domain/DateRange.ts +++ b/src/chronology/domain/DateRange.ts @@ -18,25 +18,32 @@ export default class DateRange { const startDateString = this._converter.toDateString(calendarType) this._converter.setToCjdn(this.end.cjdn) const endDateString = this._converter.toDateString(calendarType) + return `${this.getCompactStartDateString( + startDateString, + endDateString + )} - ${endDateString}` + } + + private getCompactStartDateString( + startDateString: string, + endDateString: string + ): string { + let startDateArray: string[] = [] const endDateArray = endDateString.split(' ').reverse() - const startDateArray: string[] = [] - for (const [index, startElement] of startDateString - .split(' ') - .reverse() - .entries()) { + const _startDateArray = startDateString.split(' ').reverse() + for (const [index, startElement] of _startDateArray.entries()) { const endElement = endDateArray[index] if (startElement !== endElement) { - startDateArray.push(startElement) + startDateArray = _startDateArray.slice(index) + break } } - // ToDo: Continue here. Verify that it works as expected - return `${startDateArray.reverse().join(' ')} - ${endDateString}` + return startDateArray.reverse().join(' ') } private setToPartialDate(date: MesopotamianDateBase): void { - const fieldsToUpdate = date.getEmptyOrBrokenFields() + const fieldsToUpdate = date.getEmptyFields() const defaultValues = this.getDefaultDateValues(date) - const startDate = this.calculateDateValues( fieldsToUpdate, defaultValues, @@ -49,7 +56,6 @@ export default class DateRange { 'end', date ) - this.setDateBasedOnType(date, startDate, 'start') this.setDateBasedOnType(date, endDate, 'end') } @@ -86,15 +92,15 @@ export default class DateRange { private setDateBasedOnType( date: MesopotamianDateBase, dateValues: { year: number; month: number; day: number }, - type: 'start' | 'end' + position: 'start' | 'end' ): void { - if (date.getType() === DateType.seleucidDate) { + if (date.dateType === DateType.seleucidDate) { this._converter.setToSeBabylonianDate( dateValues.year, dateValues.month, dateValues.day ) - } else if (date.getType() === DateType.nabonassarEraDate) { + } else if (date.dateType === DateType.nabonassarEraDate) { this._converter.setToMesopotamianDate( date.kingName as string, dateValues.year, @@ -102,22 +108,21 @@ export default class DateRange { dateValues.day ) } - - this[type] = { ...this._converter.calendar } + this[position] = { ...this._converter.calendar } } private getEndValueForPartialDate( date: MesopotamianDateBase, field: 'year' | 'month' | 'day' ): string { - const dateType = date.getType() + const { dateType } = date if (dateType === DateType.seleucidDate) { return { year: () => `${this.seleucidRangeEndYear}`, month: () => `${this.getSeleucidDateEndMonth(date)}`, day: () => `${this.getSeleucidDateEndDay(date)}`, }[field]() - } else if (DateType.nabonassarEraDate) { + } else if (dateType === DateType.nabonassarEraDate) { return { year: () => `${this.getNabonassarRangeEndYear}`, month: () => `${this.getNabonassarDateEndMonth(date)}`, @@ -132,23 +137,23 @@ export default class DateRange { } private getSeleucidRangeEndYear(date: MesopotamianDateBase): number { - return date.getEmptyOrBrokenFields().includes('year') + return date.getEmptyFields().includes('year') ? this.seleucidRangeEndYear : parseInt(date.year.value) } private getSeleucidDateEndMonth(date: MesopotamianDateBase): number { const year = this.getSeleucidRangeEndYear(date) - return date.getEmptyOrBrokenFields().includes('month') - ? this._converter.getMesopotamianMonthsOfSeYear(year).length - : parseInt(date.month.value) + return date.getEmptyFields().includes('month') + ? this._converter.getMesopotamianMonthsOfSeYear(year).slice(-1)[0].value + : parseInt(date.month.value) ?? 12 } private getSeleucidDateEndDay(date: MesopotamianDateBase): number { const year = this.getSeleucidRangeEndYear(date) const month = this.getSeleucidDateEndMonth(date) this._converter.setToSeBabylonianDate(year, month, 1) - return this._converter.calendar.mesopotamianMonthLength ?? 29 + return this._converter.calendar.mesopotamianMonthLength ?? 28 } private get nabonassarRangeEndYear(): number { @@ -156,7 +161,7 @@ export default class DateRange { } private getNabonassarRangeEndYear(date: MesopotamianDateBase): number { - return date.getEmptyOrBrokenFields().includes('year') + return date.getEmptyFields().includes('year') ? this.nabonassarRangeEndYear : parseInt(date.year.value) } @@ -164,10 +169,8 @@ export default class DateRange { private getNabonassarDateEndMonth(date: MesopotamianDateBase): number { const year = this.getNabonassarRangeEndYear(date) this._converter.setToMesopotamianDate(date.kingName as string, year, 1, 1) - return date.getEmptyOrBrokenFields().includes('month') - ? this._converter.getMesopotamianMonthsOfSeYear( - this._converter.calendar.seBabylonianYear - ).length + return date.getEmptyFields().includes('month') + ? this._converter.getMesopotamianMonthsOfSeYear(year).slice(-1)[0].value : parseInt(date.month.value) } @@ -180,7 +183,7 @@ export default class DateRange { month, 1 ) - return this._converter.calendar.mesopotamianMonthLength ?? 29 + return this._converter.calendar.mesopotamianMonthLength ?? 28 } static getRangeFromPartialDate(date: MesopotamianDateBase): DateRange { From 2933dd0cd6df6cb1f4285b7766320b39f16c356d Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Mon, 4 Mar 2024 15:05:10 +0000 Subject: [PATCH 89/91] Refactor --- src/chronology/domain/Date.test.ts | 2 +- src/chronology/domain/DateBase.ts | 87 ++++++++----------------- src/chronology/domain/DateParameters.ts | 50 ++++++++++++++ src/chronology/domain/DateRange.ts | 3 +- 4 files changed, 80 insertions(+), 62 deletions(-) create mode 100644 src/chronology/domain/DateParameters.ts diff --git a/src/chronology/domain/Date.test.ts b/src/chronology/domain/Date.test.ts index 75099ccef..44b12a7d6 100644 --- a/src/chronology/domain/Date.test.ts +++ b/src/chronology/domain/Date.test.ts @@ -1,6 +1,6 @@ import { Eponym } from 'chronology/ui/DateEditor/Eponyms' import { MesopotamianDate } from 'chronology/domain/Date' -import { Ur3Calendar } from 'chronology/domain/DateBase' +import { Ur3Calendar } from 'chronology/domain/DateParameters' const king = { orderGlobal: 1, diff --git a/src/chronology/domain/DateBase.ts b/src/chronology/domain/DateBase.ts index c39efc3cc..123f4a28a 100644 --- a/src/chronology/domain/DateBase.ts +++ b/src/chronology/domain/DateBase.ts @@ -1,56 +1,20 @@ -import { King } from 'chronology/ui/Kings/Kings' -import { Eponym } from 'chronology/ui/DateEditor/Eponyms' import DateConverter from 'chronology/domain/DateConverter' import data from 'chronology/domain/dateConverterData.json' import _ from 'lodash' import DateRange from './DateRange' +import { + DateField, + DateProps, + DateType, + EponymDateField, + KingDateField, + ModernCalendar, + MonthField, + Ur3Calendar, + YearMonthDay, +} from 'chronology/domain/DateParameters' -export interface DateField { - value: string - isBroken?: boolean - isUncertain?: boolean -} - -export interface MonthField extends DateField { - isIntercalary?: boolean -} - -export interface KingDateField extends King { - isBroken?: boolean - isUncertain?: boolean -} - -export interface EponymDateField extends Eponym { - isBroken?: boolean - isUncertain?: boolean -} - -interface DateProps { - year: number - month: number - day: number - isApproximate: boolean - calendar: 'Julian' | 'Gregorian' -} - -export enum DateType { - seleucidDate = 'seleucidDate', - nabonassarEraDate = 'nabonassarEraDate', - assyrianDate = 'assyrianDate', - kingDate = 'kingDate', -} - -export enum Ur3Calendar { - ADAB = 'Adab', - GIRSU = 'Girsu', - IRISAGRIG = 'Irisagrig', - NIPPUR = 'Nippur', - PUZRISHDAGAN = 'Puzriš-Dagan', - UMMA = 'Umma', - UR = 'Ur', -} - -const calendarToAbbreviation = (calendar: 'Julian' | 'Gregorian'): string => +const calendarToAbbreviation = (calendar: ModernCalendar): string => ({ Julian: 'PJC', Gregorian: 'PGC' }[calendar]) export class MesopotamianDateBase { @@ -122,19 +86,21 @@ export class MesopotamianDateBase { } get dateType(): DateType | null { + let result: DateType | null = null + if (this?.year?.value && this.isSeleucidEraApplicable(this?.year?.value)) { - return DateType.seleucidDate + result = DateType.seleucidDate } else if (this.isNabonassarEraApplicable()) { - return DateType.nabonassarEraDate + result = DateType.nabonassarEraDate } else if (this.isAssyrianDateApplicable()) { - return DateType.assyrianDate + result = DateType.assyrianDate } else if (this.isKingDateApplicable()) { - return DateType.kingDate + result = DateType.kingDate } - return null + return result } - toModernDate(calendar: 'Julian' | 'Gregorian' = 'Julian'): string { + toModernDate(calendar: ModernCalendar = 'Julian'): string { const type = this.dateType if (type === null) { return '' @@ -161,13 +127,13 @@ export class MesopotamianDateBase { } private getDateProps( - calendar: 'Julian' | 'Gregorian' = 'Julian' + calendar: ModernCalendar = 'Julian' ): { year: number month: number day: number isApproximate: boolean - calendar: 'Julian' | 'Gregorian' + calendar: ModernCalendar } { return { year: parseInt(this.year.value) ?? -1, @@ -178,8 +144,8 @@ export class MesopotamianDateBase { } } - getEmptyFields(): Array<'year' | 'month' | 'day'> { - const fields: Array<'year' | 'month' | 'day'> = ['year', 'month', 'day'] + getEmptyFields(): Array { + const fields: Array = ['year', 'month', 'day'] return fields .map((field) => { if (isNaN(parseInt(this[field].value))) { @@ -187,7 +153,7 @@ export class MesopotamianDateBase { } return null }) - .filter((field) => !!field) as Array<'year' | 'month' | 'day'> + .filter((field) => !!field) as Array } private isApproximate(): boolean { @@ -252,7 +218,7 @@ export class MesopotamianDateBase { return '' } - getDateRangeString(calendar: 'Julian' | 'Gregorian'): string | undefined { + getDateRangeString(calendar: ModernCalendar): string | undefined { if (this.range !== undefined) { return this.insertDateApproximation( this.range.toDateString(calendar), @@ -288,3 +254,4 @@ export class MesopotamianDateBase { return `${isApproximate ? 'ca. ' : ''}${dateString}` } } +export { Ur3Calendar } diff --git a/src/chronology/domain/DateParameters.ts b/src/chronology/domain/DateParameters.ts new file mode 100644 index 000000000..6528a18eb --- /dev/null +++ b/src/chronology/domain/DateParameters.ts @@ -0,0 +1,50 @@ +import { King } from 'chronology/ui/Kings/Kings' +import { Eponym } from 'chronology/ui/DateEditor/Eponyms' + +export interface DateField { + value: string + isBroken?: boolean + isUncertain?: boolean +} + +export interface MonthField extends DateField { + isIntercalary?: boolean +} + +export interface KingDateField extends King { + isBroken?: boolean + isUncertain?: boolean +} + +export interface EponymDateField extends Eponym { + isBroken?: boolean + isUncertain?: boolean +} + +export type YearMonthDay = 'year' | 'month' | 'day' +export type ModernCalendar = 'Julian' | 'Gregorian' + +export interface DateProps { + year: number + month: number + day: number + isApproximate: boolean + calendar: ModernCalendar +} + +export enum DateType { + seleucidDate = 'seleucidDate', + nabonassarEraDate = 'nabonassarEraDate', + assyrianDate = 'assyrianDate', + kingDate = 'kingDate', +} + +export enum Ur3Calendar { + ADAB = 'Adab', + GIRSU = 'Girsu', + IRISAGRIG = 'Irisagrig', + NIPPUR = 'Nippur', + PUZRISHDAGAN = 'Puzriš-Dagan', + UMMA = 'Umma', + UR = 'Ur', +} diff --git a/src/chronology/domain/DateRange.ts b/src/chronology/domain/DateRange.ts index c0073c6f1..1d890604b 100644 --- a/src/chronology/domain/DateRange.ts +++ b/src/chronology/domain/DateRange.ts @@ -1,4 +1,5 @@ -import { DateType, MesopotamianDateBase } from 'chronology/domain/DateBase' +import { MesopotamianDateBase } from 'chronology/domain/DateBase' +import { DateType } from 'chronology/domain/DateParameters' import DateConverter from './DateConverter' import { CalendarProps } from './DateConverterBase' From 5780049ec7bb2ffa47f80d529c0fb4fbeb705209 Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Mon, 4 Mar 2024 15:28:27 +0000 Subject: [PATCH 90/91] Update imports --- src/chronology/application/DateSelectionMethods.ts | 5 ++++- src/chronology/application/DateSelectionState.ts | 7 +++++-- src/chronology/ui/DateEditor/DateSelectionInput.tsx | 2 +- src/chronology/ui/DateEditor/Eponyms.tsx | 2 +- src/chronology/ui/Kings/Kings.tsx | 2 +- src/fragmentarium/domain/FragmentDtos.ts | 2 +- 6 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/chronology/application/DateSelectionMethods.ts b/src/chronology/application/DateSelectionMethods.ts index 2dc218d47..4cf48bed9 100644 --- a/src/chronology/application/DateSelectionMethods.ts +++ b/src/chronology/application/DateSelectionMethods.ts @@ -3,7 +3,10 @@ import { MesopotamianDate } from 'chronology/domain/Date' import { DateFieldDto, MonthFieldDto } from 'fragmentarium/domain/FragmentDtos' import { Fragment } from 'fragmentarium/domain/fragment' import { DateSelectionStateParams } from './DateSelectionState' -import { EponymDateField, KingDateField } from 'chronology/domain/DateBase' +import { + EponymDateField, + KingDateField, +} from 'chronology/domain/DateParameters' interface SaveDateParams { date?: MesopotamianDate diff --git a/src/chronology/application/DateSelectionState.ts b/src/chronology/application/DateSelectionState.ts index 4c187a3f8..c85dc8bec 100644 --- a/src/chronology/application/DateSelectionState.ts +++ b/src/chronology/application/DateSelectionState.ts @@ -1,6 +1,9 @@ import { MesopotamianDate } from 'chronology/domain/Date' -import { EponymDateField, Ur3Calendar } from 'chronology/domain/DateBase' -import { KingDateField } from 'chronology/domain/DateBase' +import { + EponymDateField, + Ur3Calendar, + KingDateField, +} from 'chronology/domain/DateParameters' import usePromiseEffect from 'common/usePromiseEffect' import { useState } from 'react' import Bluebird from 'bluebird' diff --git a/src/chronology/ui/DateEditor/DateSelectionInput.tsx b/src/chronology/ui/DateEditor/DateSelectionInput.tsx index 7c0cf397a..2923c66b8 100644 --- a/src/chronology/ui/DateEditor/DateSelectionInput.tsx +++ b/src/chronology/ui/DateEditor/DateSelectionInput.tsx @@ -6,7 +6,7 @@ import { EponymDateField, KingDateField, Ur3Calendar, -} from 'chronology/domain/DateBase' +} from 'chronology/domain/DateParameters' import { KingField } from 'chronology/ui/Kings/Kings' import { EponymField } from 'chronology/ui/DateEditor/Eponyms' import getDateConfigs from 'chronology/application/DateSelectionInputConfig' diff --git a/src/chronology/ui/DateEditor/Eponyms.tsx b/src/chronology/ui/DateEditor/Eponyms.tsx index d924f36c0..577c94081 100644 --- a/src/chronology/ui/DateEditor/Eponyms.tsx +++ b/src/chronology/ui/DateEditor/Eponyms.tsx @@ -5,7 +5,7 @@ import _eponymsMiddleAssyrian from 'chronology/domain/EponymsMiddleAssyrian.json import _eponymsOldAssyrian from 'chronology/domain/EponymsOldAssyrian.json' import Select from 'react-select' import _ from 'lodash' -import { EponymDateField } from 'chronology/domain/DateBase' +import { EponymDateField } from 'chronology/domain/DateParameters' export interface Eponym { readonly date?: string diff --git a/src/chronology/ui/Kings/Kings.tsx b/src/chronology/ui/Kings/Kings.tsx index cc585687b..9b6a30e62 100644 --- a/src/chronology/ui/Kings/Kings.tsx +++ b/src/chronology/ui/Kings/Kings.tsx @@ -3,7 +3,7 @@ import _ from 'lodash' import 'chronology/ui/Kings/Kings.sass' import _kings from 'chronology/domain/Kings.json' import Select, { ValueType } from 'react-select' -import { KingDateField } from 'chronology/domain/DateBase' +import { KingDateField } from 'chronology/domain/DateParameters' export interface King { orderGlobal: number diff --git a/src/fragmentarium/domain/FragmentDtos.ts b/src/fragmentarium/domain/FragmentDtos.ts index 23debff90..179fecbf1 100644 --- a/src/fragmentarium/domain/FragmentDtos.ts +++ b/src/fragmentarium/domain/FragmentDtos.ts @@ -7,7 +7,7 @@ import { EponymDateField, KingDateField, Ur3Calendar, -} from 'chronology/domain/DateBase' +} from 'chronology/domain/DateParameters' import { ArchaeologyDto } from './archaeologyDtos' import { MuseumKey } from './museum' From 92ee0d2c0f5ac7919007bc524bf38f933d9d8bb1 Mon Sep 17 00:00:00 2001 From: Ilya Khait Date: Tue, 5 Mar 2024 22:18:37 +0000 Subject: [PATCH 91/91] Fix end year in Nabonassar ranges --- src/chronology/domain/Date.test.ts | 13 +++++++++++++ src/chronology/domain/DateBase.ts | 4 ++++ src/chronology/domain/DateRange.ts | 14 ++++++-------- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/chronology/domain/Date.test.ts b/src/chronology/domain/Date.test.ts index 44b12a7d6..856297863 100644 --- a/src/chronology/domain/Date.test.ts +++ b/src/chronology/domain/Date.test.ts @@ -197,6 +197,19 @@ describe('MesopotamianDate', () => { ) }) + it('returns the correct string representation (Nabonassar era, king only)', () => { + const date = new MesopotamianDate({ + year: { value: '' }, + month: { value: '' }, + day: { value: '' }, + king: nabonassarEraKing, + isSeleucidEra: false, + }) + expect(date.toString()).toBe( + 'Darius I (ca. 14 April 521 - 5 April 485 BCE PJC | ca. 8 April 521 - 31 March 485 BCE PGC)' + ) + }) + it('returns the correct string representation (Ur III)', () => { const date = new MesopotamianDate({ year: { value: '10' }, diff --git a/src/chronology/domain/DateBase.ts b/src/chronology/domain/DateBase.ts index 123f4a28a..7630f4004 100644 --- a/src/chronology/domain/DateBase.ts +++ b/src/chronology/domain/DateBase.ts @@ -55,6 +55,10 @@ export class MesopotamianDateBase { this.isSeleucidEra = isSeleucidEra this.isAssyrianDate = isAssyrianDate this.ur3Calendar = ur3Calendar + this.setRange() + } + + private setRange(): void { if ( this.getEmptyFields().length > 0 && [DateType.nabonassarEraDate, DateType.seleucidDate].includes( diff --git a/src/chronology/domain/DateRange.ts b/src/chronology/domain/DateRange.ts index 1d890604b..1440742d9 100644 --- a/src/chronology/domain/DateRange.ts +++ b/src/chronology/domain/DateRange.ts @@ -125,7 +125,7 @@ export default class DateRange { }[field]() } else if (dateType === DateType.nabonassarEraDate) { return { - year: () => `${this.getNabonassarRangeEndYear}`, + year: () => `${this.getNabonassarRangeEndYear(date)}`, month: () => `${this.getNabonassarDateEndMonth(date)}`, day: () => `${this.getNabonassarDateEndDay(date)}`, }[field]() @@ -157,14 +157,12 @@ export default class DateRange { return this._converter.calendar.mesopotamianMonthLength ?? 28 } - private get nabonassarRangeEndYear(): number { - return this._converter.latestDate.regnalYears ?? 1 - } - private getNabonassarRangeEndYear(date: MesopotamianDateBase): number { - return date.getEmptyFields().includes('year') - ? this.nabonassarRangeEndYear - : parseInt(date.year.value) + if (!date.getEmptyFields().includes('year')) { + return parseInt(date.year.value) + } + this._converter.setToMesopotamianDate(date.kingName as string, 1, 1, 1) + return this._converter.calendar.regnalYears ?? 1 } private getNabonassarDateEndMonth(date: MesopotamianDateBase): number {