Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

514
LINES

< > BotCompany Repo | #1005277 // Scenarios (old, now called "concepts")

JavaX fragment (include)

1  
// A concept should be an object, not just a string.
2  
3  
sclass Scenario {
4  
  Map<Long, Concept> concepts = synchroTreeMap();
5  
  new HashMap<Class, O> perClassData;
6  
  S programID;
7  
  long idCounter;
8  
  volatile long changes = 1, changesWritten;
9  
  volatile java.util.Timer autoSaver;
10  
  volatile bool savingConcepts;
11  
  
12  
  *() { }
13  
  *(S *programID) {}
14  
  
15  
  long newID() {
16  
    do {
17  
      ++idCounter;
18  
    } while (hasConcept(idCounter));
19  
    ret idCounter;
20  
  }
21  
  
22  
  synchronized void loadConceptsFrom(S programID) {
23  
    clearConcepts();
24  
    DynamicObject_loading = true;
25  
    try {
26  
      readLocally2(this, programID, "concepts");
27  
      assignConceptsToUs();
28  
      readLocally2(this, programID, "idCounter");
29  
    } finally {
30  
      DynamicObject_loading = false;
31  
    }
32  
  }
33  
  
34  
  void assignConceptsToUs() {
35  
    for (Concept c : values(concepts)) {
36  
      c.scenario = this;
37  
      callOpt(c, "_doneLoading2");
38  
    }
39  
  }
40  
  
41  
  synchronized void loadConcepts() {
42  
    loadConceptsFrom(progID());
43  
  }
44  
  
45  
  S progID() {
46  
    ret programID == null ? programID() : programID;
47  
  }
48  
  
49  
  Concept getConcept(S id) {
50  
    ret empty(id) ? null : getConcept(parseLong(id));
51  
  }
52  
  
53  
  Concept getConcept(long id) {
54  
    ret (Concept) concepts.get((long) id);
55  
  }
56  
  
57  
  Concept getConcept(PassRef ref) {
58  
    ret ref == null ? null : getConcept(ref.longID());
59  
  }
60  
  
61  
  bool hasConcept(long id) {
62  
    ret concepts.containsKey((long) id);
63  
  }
64  
  
65  
  void deleteConcept(long id) {
66  
    Concept c = getConcept(id);
67  
    if (c == null)
68  
      print("Concept " + id + " not found");
69  
    else
70  
      c.delete();
71  
  }
72  
  
73  
  // call in only one thread
74  
  void saveConceptsIfDirty() {
75  
    savingConcepts = true;
76  
    try {
77  
      S s;
78  
      synchronized(main.class) {
79  
        if (changes == changesWritten) ret;
80  
        changesWritten = changes;
81  
        saveLocally2(this, "idCounter");
82  
        s = structure(cloneMap(concepts));
83  
      }
84  
      print("Saving " + l(s) + " chars (" + changesWritten + ")");
85  
      saveTextFile(getProgramFile("concepts.structure"), s);
86  
      copyFile(getProgramFile("concepts.structure"), getProgramFile("concepts.structure.backup" + ymd() + "-" + formatInt(hours(), 2)));
87  
    } finally {
88  
      savingConcepts = false;
89  
    }
90  
  }
91  
  
92  
  void saveConcepts() {
93  
    saveConceptsIfDirty();
94  
  }
95  
  
96  
  void clearConcepts() {
97  
    concepts.clear();
98  
    change();
99  
  }
100  
  
101  
  synchronized void change() {
102  
    ++changes;
103  
  }
104  
  
105  
  // auto-save every second if dirty
106  
  synchronized void autoSaveConcepts() {
107  
    if (autoSaver == null)
108  
      autoSaver = doEvery(1000, r { saveConcepts(); });
109  
  }
110  
  
111  
  void cleanMeUp() {
112  
    if (autoSaver != null) {
113  
      autoSaver.cancel();
114  
      autoSaver = null;
115  
    }
116  
    while (savingConcepts) sleep(10);
117  
    saveConceptsIfDirty();
118  
  }
119  
  
120  
  Map<Long, S> getIDsAndNames() {
121  
    new Map<Long, S> map;
122  
    Map<Long, Concept> cloned = cloneMap(concepts);
123  
    for (long id : keys(cloned)) 
124  
      map.put(id, cloned.get(id).className);
125  
    ret map;
126  
  }
127  
  
128  
  void deleteConcepts(L<Long> ids) {
129  
    concepts.keySet().removeAll(ids);
130  
  }
131  
  
132  
  <A extends Concept> A findBackRef(Concept c, Class<A> type) {
133  
    ret findBackRefOfType(c, type);
134  
  }
135  
  
136  
  <A extends Concept> A findBackRefOfType(Concept c, Class<A> type) {
137  
    for (Concept.Ref r : c.backRefs)
138  
      if (instanceOf(r.concept(), type))
139  
        ret (A) r.concept();
140  
    null;
141  
  }
142  
  
143  
  <A extends Concept> L<A> findBackRefs(Concept c, Class<A> type) {
144  
    new L<A> l;
145  
    for (Concept.Ref r : c.backRefs)
146  
      if (instanceOf(r.concept(), type))
147  
        l.add((A) r.concept());
148  
    ret l;
149  
  }
150  
  
151  
  <A extends Concept> A conceptOfType(Class<A> type) {
152  
    ret firstOfType(allConcepts(), type);
153  
  }
154  
  
155  
  <A extends Concept> L<A> conceptsOfType(Class<A> type) {
156  
    ret filterByType(allConcepts(), type);
157  
  }
158  
  
159  
  <A extends Concept> L<A> listConcepts(Class<A> type) {
160  
    ret conceptsOfType(type);
161  
  }
162  
  
163  
  <A extends Concept> L<A> list(Class<A> type) {
164  
    ret conceptsOfType(type);
165  
  }
166  
  
167  
  L<Concept> conceptsOfType(S type) {
168  
    ret filterByDynamicType(allConcepts(), "main$" + type);
169  
  }
170  
  
171  
  bool hasConceptOfType(Class<? extends Concept> type) {
172  
    ret hasType(allConcepts(), type);
173  
  }
174  
  
175  
  void persistConcepts() {
176  
    loadConcepts();
177  
    autoSaveConcepts();
178  
  }
179  
  
180  
  // We love synonyms
181  
  void conceptPersistence() {
182  
    persistConcepts();
183  
  }
184  
    
185  
  // Runs r if there is no concept of that type
186  
  <A extends Concept> A ensureHas(Class<A> c, Runnable r) {
187  
    A a = conceptOfType(c);
188  
    if (a == null) {
189  
      r.run();
190  
      a = conceptOfType(c);
191  
      if (a == null)
192  
        fail("Concept not made by " + r + ": " + shortClassName(c));
193  
    }
194  
    ret a;
195  
  }
196  
  
197  
  // Ensures that every concept of type c1 is ref'd by a concept of
198  
  // type c2.
199  
  // Type of func: voidfunc(concept)
200  
  void ensureHas(Class<? extends Concept> c1, Class<? extends Concept> c2, O func) {
201  
    for (Concept a : conceptsOfType(c1)) {
202  
      Concept b = findBackRef(a, c2);
203  
      if (b == null) {
204  
        callF(func, a);
205  
        b = findBackRef(a, c2);
206  
        if (b == null)
207  
          fail("Concept not made by " + func + ": " + shortClassName(c2));
208  
      }
209  
    }
210  
  }
211  
  
212  
  // Type of func: voidfunc(concept)
213  
  void forEvery(Class<? extends Concept> type, O func) {
214  
    for (Concept c : conceptsOfType(type))
215  
      callF(func, c);
216  
  }
217  
  
218  
  int deleteAll(Class<? extends Concept> type) {
219  
    L<Concept> l = (L) conceptsOfType(type);
220  
    for (Concept c : l) c.delete();
221  
    ret l(l);
222  
  }
223  
  
224  
  Collection<Concept> allConcepts() {
225  
    synchronized(concepts) {
226  
      ret new L(values(concepts));
227  
    }
228  
  }
229  
  
230  
  Concept cnew(S name, O... values) {
231  
    Class<? extends Concept> cc = findClass(name);
232  
    Concept c = cc != null ? nuObject(cc) : new Concept(name);
233  
    csetAll(c, values);
234  
    ret c;
235  
  }
236  
  
237  
  void csetAll(Concept c, O... values) {
238  
    for (int i = 0; i+1 < l(values); i += 2)
239  
      cset(c, (S) values[i], values[i+1]);
240  
  }
241  
  
242  
  void cset(Concept c, S field, O value) ctex {
243  
    Field f = setOpt_findField(c.getClass(), field);
244  
    print("cset: " + c.id + " " + field + " " + struct(value) + " " + f);
245  
    if (value instanceof PassRef) value = getConcept((PassRef) value);
246  
    if (f == null)
247  
      c.fieldValues.put(field, value instanceof Concept ? c.new Ref((Concept) value) : value);
248  
    else if (isSubtypeOf(f.getType(), Concept.Ref.class))
249  
      ((Concept.Ref) f.get(c)).set((Concept) value);
250  
    else
251  
      f.set(c, value);
252  
    change();
253  
  }
254  
  
255  
  O cget(Concept c, S field) {
256  
    O o = getOpt(c, field);
257  
    if (o instanceof Concept.Ref) ret ((Concept.Ref) o).get();
258  
    ret o;
259  
  }
260  
  
261  
  PassRef toPassRef(Concept c) {
262  
    ret new PassRef(c);
263  
  }
264  
  
265  
  // inter-process methods
266  
  
267  
  PassRef xnew(S name, O... values) {
268  
    ret new PassRef(cnew(name, values));
269  
  }
270  
  
271  
  void xset(long id, S field, O value) {
272  
    xset(new PassRef(id), field, value);
273  
  }
274  
  
275  
  void xset(PassRef c, S field, O value) {
276  
    if (value instanceof PassRef)
277  
      value = getConcept((PassRef) value);
278  
    cset(getConcept(c), field, value);
279  
  }
280  
  
281  
  O xget(long id, S field) {
282  
    ret xget(new PassRef(id), field);
283  
  }
284  
  
285  
  O xget(PassRef c, S field) {
286  
    ret cget(getConcept(c), field);
287  
  }
288  
  
289  
  void xdelete(long id) {
290  
    xdelete(new PassRef(id));
291  
  }
292  
  
293  
  void xdelete(PassRef c) {
294  
    getConcept(c).delete();
295  
  }
296  
  
297  
  L<PassRef> xlist() {
298  
    ret map("toPassRef", allConcepts());
299  
  }
300  
  
301  
  L<PassRef> xlist(S className) {
302  
    ret map("toPassRef", conceptsOfType(className));
303  
  }
304  
}
305  
306  
static volatile new Scenario mainScenario; // Where we create new concepts
307  
308  
sclass Concept extends DynamicObject {
309  
  transient Scenario scenario; // Where we belong
310  
  long id;
311  
  O madeBy;
312  
  //double energy;
313  
  //bool defunct;
314  
  long created;
315  
  
316  
  // used only internally (cnew)
317  
  *(S className) {
318  
    super(className);
319  
    _created();
320  
  }
321  
  
322  
  *() {
323  
    if (!DynamicObject_loading) {
324  
      className = shortClassName(this);
325  
      print("New concept of type " + className);
326  
      _created();
327  
    }
328  
  }
329  
  
330  
  new L<Ref> refs;
331  
  new L<Ref> backRefs;
332  
333  
  void _created() {
334  
    scenario = mainScenario;
335  
    id = scenario.newID();
336  
    created = now();
337  
    scenario.concepts.put((long) id, this);
338  
    scenario.change();
339  
  }
340  
  
341  
  void put(S field, O value) {
342  
    fieldValues.put(field, value);
343  
    scenario.change();
344  
  }
345  
  
346  
  O get(S field) {
347  
    ret fieldValues.get(field);
348  
  }
349  
  
350  
  class Ref<A extends Concept> {
351  
    A value;
352  
    
353  
    *() {
354  
      if (!DynamicObject_loading) refs.add(this);
355  
    }
356  
    
357  
    *(A *value) {
358  
      refs.add(this);
359  
      index();
360  
    }
361  
    
362  
    // get owning concept (source)
363  
    Concept concept() {
364  
      ret Concept.this;
365  
    }
366  
    
367  
    // get target
368  
    A get() {
369  
      ret value;
370  
    }
371  
    
372  
    void set(A a) {
373  
      if (a == value) ret;
374  
      unindex();
375  
      value = a;
376  
      index();
377  
    }
378  
    
379  
    void set(Ref<A> ref) {
380  
      set(ref.get());
381  
    }
382  
    
383  
    void index() { 
384  
      if (value != null)
385  
        value.backRefs.add(this);
386  
      scenario.change();
387  
    }
388  
    
389  
    void unindex() {
390  
      if (value != null)
391  
        value.backRefs.remove(this);
392  
    }
393  
  }
394  
  
395  
  class RefL<A extends Concept> extends AbstractList<Concept> {
396  
    new L<Ref<A>> l;
397  
    
398  
    public A set(int i, A o) {
399  
      A prev = l.get(i).get();
400  
      l.get(i).set(o);
401  
      ret prev;
402  
    }
403  
    
404  
    public void add(int i, A o) {
405  
      l.add(i, new Ref(o));
406  
    }
407  
    
408  
    public A get(int i) {
409  
      ret l.get(i).get();
410  
    }
411  
    
412  
    public A remove(int i) {
413  
      ret l.remove(i).get();
414  
    }
415  
    
416  
    public int size() {
417  
      ret l.size();
418  
    }
419  
  }
420  
  
421  
  void delete() {
422  
    scenario.concepts.remove((long) id);
423  
    id = 0;
424  
    //name = "[defunct " + name + "]";
425  
    //defunct = true;
426  
    //energy = 0;
427  
    for (Ref r : refs)
428  
      r.unindex();
429  
    refs.clear();
430  
    scenario.change();
431  
  }
432  
  
433  
  BaseXRef export() {
434  
    ret new BaseXRef(scenario.programID, id);
435  
  }
436  
  
437  
  // notice system of a change in this object
438  
  void change() {
439  
    scenario.change();
440  
  }
441  
} // class Concept
442  
443  
// for inter-process communication
444  
// prepared for string ids if we do them later
445  
sclass PassRef {
446  
  S id;
447  
  
448  
  *() {} // make serialisation happy
449  
  *(long id) { this.id = str(id); }
450  
  *(Concept c) { this(c.id); }
451  
  long longID() { ret parseLong(id); }
452  
  
453  
  public S toString() {
454  
    ret id;
455  
  }
456  
}
457  
458  
sclass Event extends Concept {}
459  
460  
// Reference to a concept in another program
461  
sclass BaseXRef {
462  
  S programID;
463  
  long id;
464  
    
465  
  *() {}
466  
  *(S *programID, long *id) {}
467  
  
468  
  public bool equals(O o) {
469  
    if (!(o instanceof BaseXRef)) false;
470  
    BaseXRef r = cast o;
471  
    ret eq(programID, r.programID) && eq(id, r.id);
472  
  }
473  
  
474  
  public int hashCode() {
475  
    ret programID.hashCode() + (int) id;
476  
  }
477  
}
478  
479  
// BaseXRef as a concept
480  
sclass XRef extends Concept {
481  
  BaseXRef ref;
482  
  
483  
  *() {}
484  
  *(BaseXRef *ref) { _doneLoading2(); }
485  
  
486  
  // after we have been added to scenario
487  
  void _doneLoading2() {
488  
    getIndex().put(ref, this);
489  
  }
490  
    
491  
  HashMap<BaseXRef, XRef> getIndex() {
492  
    ret getXRefIndex(scenario);
493  
  }
494  
}
495  
496  
static synchronized HashMap<BaseXRef, XRef> getXRefIndex(Scenario scenario) {
497  
  HashMap cache = (HashMap) scenario.perClassData.get(XRef.class);
498  
  if (cache == null)
499  
    scenario.perClassData.put(XRef.class, cache = new HashMap);
500  
  ret cache;
501  
}
502  
503  
// uses mainScenario
504  
static XRef lookupOrCreateXRef(BaseXRef ref) {
505  
  XRef xref = getXRefIndex(mainScenario).get(ref);
506  
  if (xref == null)
507  
    xref = new XRef(ref);
508  
  ret xref;
509  
}
510  
511  
svoid loadAndAutoSaveConcepts {
512  
  mainScenario.loadConcepts();
513  
  mainScenario.autoSaveConcepts();
514  
}

Author comment

Began life as a copy of #1004863

download  show line numbers  debug dex  old transpilations   

Travelled to 14 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, ddnzoavkxhuk, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1005277
Snippet name: Scenarios (old, now called "concepts")
Eternal ID of this version: #1005277/2
Text MD5: fb0fb8901c4eef87e5da57209580e32f
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2019-07-18 13:55:17
Source code size: 11918 bytes / 514 lines
Pitched / IR pitched: No / No
Views / Downloads: 421 / 617
Version history: 1 change(s)
Referenced in: [show references]