evt-model.service.ts 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. import { Injectable } from '@angular/core';
  2. import { combineLatest, Observable } from 'rxjs';
  3. import { map, shareReplay, switchMap } from 'rxjs/operators';
  4. import { NamedEntities, NamedEntityOccurrence, OriginalEncodingNodeType, Page, ZoneHotSpot, ZoneLine, LemmatizedEntities, LemmatizedEntityOccurrence } from '../models/evt-models';
  5. import { Map } from '../utils/js-utils';
  6. import { EditionDataService } from './edition-data.service';
  7. import { ApparatusEntriesParserService } from './xml-parsers/apparatus-entries-parser.service';
  8. import { CharacterDeclarationsParserService } from './xml-parsers/character-declarations-parser.service';
  9. import { FacsimileParserService } from './xml-parsers/facsimile-parser.service';
  10. import { LinesVersesParserService } from './xml-parsers/lines-verses-parser.service';
  11. import { MsDescParserService } from './xml-parsers/ms-desc-parser.service';
  12. import { NamedEntitiesParserService } from './xml-parsers/named-entities-parser.service';
  13. import { PrefatoryMatterParserService } from './xml-parsers/prefatory-matter-parser.service';
  14. import { StructureXmlParserService } from './xml-parsers/structure-xml-parser.service';
  15. import { WitnessesParserService } from './xml-parsers/witnesses-parser.service';
  16. // add by FS
  17. import { LemmatizedEntitiesParserService } from './xml-parsers/lemmatized-entities-parser.service';
  18. @Injectable({
  19. providedIn: 'root',
  20. })
  21. export class EVTModelService {
  22. public readonly editionSource$: Observable<OriginalEncodingNodeType> = this.editionDataService.parsedEditionSource$
  23. .pipe(
  24. shareReplay(1),
  25. );
  26. public readonly title$ = this.editionSource$.pipe(
  27. map((source) => this.prefatoryMatterParser.parseEditionTitle(source)),
  28. shareReplay(1),
  29. );
  30. public readonly projectInfo$ = this.prefatoryMatterParser.projectInfo$.pipe(
  31. shareReplay(1),
  32. );
  33. public readonly pages$: Observable<Page[]> = this.editionSource$.pipe(
  34. map((source) => this.editionStructureParser.parsePages(source).pages),
  35. shareReplay(1),
  36. );
  37. // NAMED ENTITIES
  38. public readonly parsedLists$ = this.editionSource$.pipe(
  39. map((source) => this.namedEntitiesParser.parseLists(source)),
  40. shareReplay(1),
  41. );
  42. public readonly persons$ = this.parsedLists$.pipe(
  43. map(({ lists, entities }) => (this.namedEntitiesParser.getResultsByType(lists, entities, ['person', 'personGrp']))),
  44. );
  45. public readonly places$ = this.parsedLists$.pipe(
  46. map(({ lists, entities }) => this.namedEntitiesParser.getResultsByType(lists, entities, ['place'])),
  47. );
  48. public readonly organizations$ = this.parsedLists$.pipe(
  49. map(({ lists, entities }) => this.namedEntitiesParser.getResultsByType(lists, entities, ['org'])),
  50. );
  51. public readonly relations$ = this.parsedLists$.pipe(
  52. map(({ relations }) => relations),
  53. );
  54. public readonly events$ = this.parsedLists$.pipe(
  55. map(({ lists, entities }) => this.namedEntitiesParser.getResultsByType(lists, entities, ['event'])),
  56. );
  57. public readonly verses$ = this.editionSource$.pipe(
  58. map((source) => this.linesVersesParser.parseVerses(source)),
  59. shareReplay(1),
  60. );
  61. public readonly lines$ = this.editionSource$.pipe(
  62. map((source) => this.linesVersesParser.parseLines(source)),
  63. shareReplay(1),
  64. );
  65. public readonly namedEntities$: Observable<NamedEntities> = combineLatest([
  66. this.persons$,
  67. this.places$,
  68. this.organizations$,
  69. this.relations$,
  70. this.events$,
  71. ]).pipe(
  72. map(([persons, places, organizations, relations, events]) => ({
  73. all: {
  74. lists: [...persons.lists, ...places.lists, ...organizations.lists, ...events.lists],
  75. entities: [...persons.entities, ...places.entities, ...organizations.entities, ...events.entities],
  76. },
  77. persons,
  78. places,
  79. organizations,
  80. relations,
  81. events,
  82. })),
  83. shareReplay(1),
  84. );
  85. public entitiesOccurrences$: Observable<Map<NamedEntityOccurrence[]>> = this.pages$.pipe(
  86. map((pages) => this.namedEntitiesParser.parseNamedEntitiesOccurrences(pages)),
  87. shareReplay(1),
  88. );
  89. public lemsOccurrences$: Observable<Map<LemmatizedEntityOccurrence[]>> = this.pages$.pipe(
  90. map((pages) => this.lemmatizedEntitiesParser.parseLemmatizedEntitiesOccurrences(pages)),
  91. shareReplay(1),
  92. );
  93. // WITNESSES
  94. public readonly witnessesData$ = this.editionSource$.pipe(
  95. map((source) => this.witnessesParser.parseWitnessesData(source)),
  96. shareReplay(1),
  97. );
  98. public readonly witnesses$ = this.witnessesData$.pipe(
  99. map(({ witnesses }) => witnesses),
  100. shareReplay(1),
  101. );
  102. public readonly groups$ = this.witnessesData$.pipe(
  103. map(({ groups }) => groups),
  104. shareReplay(1),
  105. );
  106. // APPARATUS ENTRIES
  107. public readonly appEntries$ = this.editionSource$.pipe(
  108. map((source) => this.apparatusParser.parseAppEntries(source)),
  109. shareReplay(1),
  110. );
  111. public readonly significantReadings$ = this.appEntries$.pipe(
  112. map((appEntries) => this.apparatusParser.getSignificantReadings(appEntries)),
  113. shareReplay(1),
  114. );
  115. public readonly significantReadingsNumber$ = this.significantReadings$.pipe(
  116. map((signRdgs) => this.apparatusParser.getSignificantReadingsNumber(signRdgs)),
  117. shareReplay(1),
  118. );
  119. public readonly appVariance$ = this.witnesses$.pipe(
  120. switchMap((witList) => {
  121. return this.significantReadingsNumber$.pipe(
  122. map((signRdgsNum) => this.apparatusParser.getAppVariance(signRdgsNum, witList)),
  123. );
  124. }),
  125. shareReplay(1),
  126. );
  127. // FACSIMILE
  128. public readonly surfaces$ = this.editionSource$.pipe(
  129. map((source) => this.facsimileParser.parseSurfaces(source)),
  130. shareReplay(1),
  131. );
  132. public readonly hsLines$ = this.surfaces$.pipe(
  133. map((surfaces) => surfaces.reduce((x: ZoneLine[], y) => x.concat(y.zones.lines), [])),
  134. shareReplay(1),
  135. );
  136. public readonly hotspots$ = this.surfaces$.pipe(
  137. map((surfaces) => surfaces.reduce((x: ZoneHotSpot[], y) => x.concat(y.zones.hotspots), [])),
  138. shareReplay(1),
  139. );
  140. // CHAR DECL
  141. public readonly characters$ = this.editionSource$.pipe(
  142. map((source) => this.characterDeclarationsParser.parseChars(source)),
  143. shareReplay(1),
  144. );
  145. public readonly glyphs$ = this.editionSource$.pipe(
  146. map((source) => this.characterDeclarationsParser.parseGlyphs(source)),
  147. shareReplay(1),
  148. );
  149. public readonly specialChars$ = combineLatest([
  150. this.characters$,
  151. this.glyphs$,
  152. ]).pipe(
  153. map(([chars, glyphs]) => chars.concat(glyphs)),
  154. );
  155. public readonly msDesc$ = this.editionSource$.pipe(
  156. map((source) => this.msDescParser.parseMsDesc(source)),
  157. shareReplay(1),
  158. );
  159. // add by FS
  160. // LEMMA ENTITIES
  161. public readonly parsedLemLists$ = this.editionSource$.pipe(
  162. map((source) => this.lemmatizedEntitiesParser.parseLemLists(source)),
  163. shareReplay(1),
  164. );
  165. public readonly item$ = this.parsedLemLists$.pipe(
  166. map(({ lemlists, lementities }) => (this.lemmatizedEntitiesParser.getResultsByType(lemlists, lementities, ['item', 'lem', 'w']))),
  167. );
  168. public readonly lemmas$ = this.parsedLemLists$.pipe(
  169. map(({ lemlists, lementities }) => (this.lemmatizedEntitiesParser.getResultsByType(lemlists, lementities, ['item', 'lem', 'w']))),
  170. );
  171. public readonly lemmatizedEntities$: Observable<LemmatizedEntities> = combineLatest([
  172. this.item$,
  173. this.lemmas$,
  174. this.relations$,
  175. ]).pipe(
  176. map(([item, lemmas, relations]) => ({
  177. all: {
  178. lemlists: [...item.lemlists, ...lemmas.lemlists],
  179. lementities: [...item.lementities],
  180. },
  181. item,
  182. lemmas,
  183. relations,
  184. })),
  185. shareReplay(1),
  186. );
  187. public entitiesLemOccurrences$: Observable<Map<LemmatizedEntityOccurrence[]>> = this.pages$.pipe(
  188. map((pages) => this.lemmatizedEntitiesParser.parseLemmatizedEntitiesOccurrences(pages)),
  189. shareReplay(1),
  190. );
  191. constructor(
  192. private editionDataService: EditionDataService,
  193. private editionStructureParser: StructureXmlParserService,
  194. private namedEntitiesParser: NamedEntitiesParserService,
  195. private prefatoryMatterParser: PrefatoryMatterParserService,
  196. private witnessesParser: WitnessesParserService,
  197. private apparatusParser: ApparatusEntriesParserService,
  198. private facsimileParser: FacsimileParserService,
  199. private characterDeclarationsParser: CharacterDeclarationsParserService,
  200. private linesVersesParser: LinesVersesParserService,
  201. private msDescParser: MsDescParserService,
  202. // add by FS
  203. private lemmatizedEntitiesParser: LemmatizedEntitiesParserService,
  204. ) {
  205. }
  206. getPage(pageId: string): Observable<Page> {
  207. return this.pages$.pipe(map((pages) => pages.find((page) => page.id === pageId)));
  208. }
  209. }