auditory_description.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import { Grammar } from '../rule_engine/grammar.js';
  2. import { Span } from './span.js';
  3. export class AuditoryItem {
  4. constructor(data = null) {
  5. this.data = data;
  6. this.prev = null;
  7. this.next = null;
  8. }
  9. }
  10. export class AuditoryList extends Set {
  11. constructor(descrs) {
  12. super();
  13. this.annotations = [];
  14. this.anchor = new AuditoryItem();
  15. this.anchor.next = this.anchor;
  16. this.anchor.prev = this.anchor;
  17. descrs.forEach((d) => {
  18. const item = new AuditoryItem(d);
  19. if (d.annotation) {
  20. this.annotations.push(item);
  21. }
  22. this.push(item);
  23. });
  24. }
  25. first() {
  26. return this.empty ? null : this.anchor.next;
  27. }
  28. last() {
  29. return this.empty ? null : this.anchor.prev;
  30. }
  31. push(item) {
  32. item.next = this.anchor;
  33. item.prev = this.anchor.prev;
  34. item.prev.next = item;
  35. this.anchor.prev = item;
  36. super.add(item);
  37. }
  38. pop() {
  39. const item = this.last();
  40. if (!item) {
  41. return null;
  42. }
  43. this.delete(item);
  44. return item;
  45. }
  46. delete(item) {
  47. if (!this.has(item)) {
  48. return false;
  49. }
  50. super.delete(item);
  51. item.prev.next = item.next;
  52. item.next = item.prev;
  53. return true;
  54. }
  55. insertAfter(descr, item) {
  56. this.insertBefore(descr, item.next);
  57. }
  58. insertBefore(descr, item) {
  59. const nitem = new AuditoryItem(descr);
  60. if (!item || !this.has(item)) {
  61. this.push(nitem);
  62. return;
  63. }
  64. item.prev.next = nitem;
  65. nitem.prev = item.prev;
  66. nitem.next = item;
  67. item.prev = nitem;
  68. }
  69. prevText(item) {
  70. do {
  71. item = item.prev;
  72. } while (item !== this.anchor && !item.data.text);
  73. return item === this.anchor ? null : item;
  74. }
  75. *[Symbol.iterator]() {
  76. let current = this.anchor.next;
  77. while (current !== this.anchor) {
  78. yield current;
  79. current = current.next;
  80. }
  81. }
  82. nextText(item) {
  83. while (item !== this.anchor && !item.data.text) {
  84. item = item.next;
  85. }
  86. return item;
  87. }
  88. clear() {
  89. this.anchor.next = this.anchor;
  90. this.anchor.prev = this.anchor;
  91. super.clear();
  92. }
  93. empty() {
  94. return this.anchor.prev === this.anchor && this.anchor === this.anchor.next;
  95. }
  96. toList() {
  97. const result = [];
  98. let item = this.anchor.next;
  99. while (item !== this.anchor) {
  100. result.push(item.data);
  101. item = item.next;
  102. }
  103. return result;
  104. }
  105. }
  106. export class AuditoryDescription {
  107. static create(args, flags = {}) {
  108. args.text = Grammar.getInstance().apply(args.text, flags);
  109. return new AuditoryDescription(args);
  110. }
  111. constructor({ context, text, userValue, annotation, attributes, personality, layout }) {
  112. this.context = context || '';
  113. this.text = text || '';
  114. this.userValue = userValue || '';
  115. this.annotation = annotation || '';
  116. this.attributes = attributes || {};
  117. this.personality = personality || {};
  118. this.layout = layout || '';
  119. }
  120. isEmpty() {
  121. return (this.context.length === 0 &&
  122. this.text.length === 0 &&
  123. this.userValue.length === 0 &&
  124. this.annotation.length === 0);
  125. }
  126. clone() {
  127. let personality;
  128. if (this.personality) {
  129. personality = {};
  130. for (const [key, val] of Object.entries(this.personality)) {
  131. personality[key] = val;
  132. }
  133. }
  134. let attributes;
  135. if (this.attributes) {
  136. attributes = {};
  137. for (const [key, val] of Object.entries(this.attributes)) {
  138. attributes[key] = val;
  139. }
  140. }
  141. return new AuditoryDescription({
  142. context: this.context,
  143. text: this.text,
  144. userValue: this.userValue,
  145. annotation: this.annotation,
  146. personality: personality,
  147. attributes: attributes,
  148. layout: this.layout
  149. });
  150. }
  151. toString() {
  152. return ('AuditoryDescription(context="' +
  153. this.context +
  154. '" ' +
  155. ' text="' +
  156. this.text +
  157. '" ' +
  158. ' userValue="' +
  159. this.userValue +
  160. '" ' +
  161. ' annotation="' +
  162. this.annotation +
  163. '")');
  164. }
  165. descriptionString() {
  166. return this.context && this.text
  167. ? this.context + ' ' + this.text
  168. : this.context || this.text;
  169. }
  170. descriptionSpan() {
  171. return Span.stringAttr(this.descriptionString(), this.attributes);
  172. }
  173. equals(that) {
  174. return (this.context === that.context &&
  175. this.text === that.text &&
  176. this.userValue === that.userValue &&
  177. this.annotation === that.annotation);
  178. }
  179. }