From 85d5e9b9b3f7e2c0028dbdb5c1b0390d1cc8acc5 Mon Sep 17 00:00:00 2001
From: David Sehnal <david.sehnal@gmail.com>
Date: Wed, 4 Oct 2017 14:34:05 +0200
Subject: [PATCH] Computation API cleanup

---
 src/reader/cif/text/parser.ts       | 22 ++++------------------
 src/reader/common/text/tokenizer.ts |  2 +-
 src/script.ts                       |  8 ++++----
 src/utils/computation.ts            | 23 +++++++++++++++--------
 4 files changed, 24 insertions(+), 31 deletions(-)

diff --git a/src/reader/cif/text/parser.ts b/src/reader/cif/text/parser.ts
index 22191b0c5..764712579 100644
--- a/src/reader/cif/text/parser.ts
+++ b/src/reader/cif/text/parser.ts
@@ -456,7 +456,6 @@ interface LoopReadState {
 }
 
 function readLoopChunk(state: LoopReadState, chunkSize: number) {
-    //console.log(chunkSize);
     const { tokenizer, tokens, fieldCount } = state;
     let tokenCount = state.tokenCount;
     let counter = 0;
@@ -466,20 +465,13 @@ function readLoopChunk(state: LoopReadState, chunkSize: number) {
         counter++;
     }
     state.tokenCount = tokenCount;
-    return counter; //tokenizer.currentTokenType === CifTokenType.Value;
+    return counter;
 }
 
 function readLoopChunks(state: LoopReadState) {
-    const { chunker } = state.tokenizer;
-    // while (readLoopChunk(state, computation.chunkSize)) {
-    //     if (computation.requiresUpdate) {
-    //         await computation.updateProgress('Parsing...', void 0, state.tokenizer.position, state.tokenizer.data.length);
-    //     }
-    // }
-
-    return chunker.process(
+    return state.tokenizer.chunker.process(
         chunkSize => readLoopChunk(state, chunkSize),
-        update => update('Parsing...', void 0, state.tokenizer.position, state.tokenizer.data.length));
+        update => update({ message: 'Parsing...', current: state.tokenizer.position, max: state.tokenizer.data.length }));
 }
 
 /**
@@ -509,12 +501,6 @@ async function handleLoop(tokenizer: TokenizerState, categories: { [name: string
         tokens
     };
 
-    // let tokenCount = 0;
-    // while (tokenizer.currentTokenType === CifTokenType.Value) {
-    //     TokenBuilder.add(tokens[(tokenCount++) % fieldCount], tokenizer.currentTokenStart, tokenizer.currentTokenEnd);
-    //     moveNext(tokenizer);
-    // }
-
     await readLoopChunks(state);
 
     if (state.tokenCount % fieldCount !== 0) {
@@ -569,7 +555,7 @@ async function parseInternal(data: string, ctx: Computation.Context) {
     //inSaveFrame = false,
     //blockSaveFrames: any;
 
-    ctx.updateProgress('Parsing...');
+    ctx.updateProgress({ message: 'Parsing...' });
 
     moveNext(tokenizer);
     while (tokenizer.currentTokenType !== CifTokenType.End) {
diff --git a/src/reader/common/text/tokenizer.ts b/src/reader/common/text/tokenizer.ts
index 314b4ff42..d84705a43 100644
--- a/src/reader/common/text/tokenizer.ts
+++ b/src/reader/common/text/tokenizer.ts
@@ -112,7 +112,7 @@ export namespace Tokenizer {
             readLinesChunk(state, linesToRead, lineTokens);
             linesAlreadyRead += linesToRead;
             return linesToRead;
-        }, update => update('Parsing...', void 0, state.position, length));
+        }, update => update({ message: 'Parsing...', current: state.position, max: length }));
 
         return lineTokens;
     }
diff --git a/src/script.ts b/src/script.ts
index 671f9f374..8612e3bc5 100644
--- a/src/script.ts
+++ b/src/script.ts
@@ -19,7 +19,7 @@ const file = 'md_1u19_trj.gro'
 async function runGro(input: string) {
     console.time('parseGro');
     const comp = Gro(input);
-    const running = comp.runObservable(Computation.observableContext({ updateRateMs: 150 }));
+    const running = comp.runObservable(Computation.observable({ updateRateMs: 150 }));
     running.subscribe(p => console.log(`[Gro] ${(p.current / p.max * 100).toFixed(2)} (${p.elapsedMs | 0}ms)`));
     const parsed = await running.result;
     console.timeEnd('parseGro');
@@ -85,8 +85,8 @@ async function runCIF(input: string | Uint8Array) {
     console.time('parseCIF');
     const comp = typeof input === 'string' ? CIF.parseText(input) : CIF.parseBinary(input);
 
-    const running = comp.runObservable(Computation.observableContext({ updateRateMs: 250 }));
-    running.subscribe(p => console.log(`[CIF] ${(p.current / p.max * 100).toFixed(2)} (${p.elapsedMs | 0}ms)`));
+    const running = comp.runObservable(Computation.observable({ updateRateMs: 250 })); // Computation.synchronous
+    running.subscribe(p => console.log(`[CIF] ${p.message} ${(p.current / p.max * 100).toFixed(2)}% (${p.elapsedMs | 0}ms)`));
     const parsed = await running.result;
     console.timeEnd('parseCIF');
     if (parsed.isError) {
@@ -137,7 +137,7 @@ import Computation from './utils/computation'
 const comp = Computation.create(async ctx => {
     for (let i = 0; i < 0; i++) {
         await new Promise(res => setTimeout(res, 500));
-        if (ctx.requiresUpdate) await ctx.updateProgress('working', void 0, i, 2);
+        if (ctx.requiresUpdate) await ctx.updateProgress({ message: 'working', current: i, max: 2 });
     }
     return 42;
 });
diff --git a/src/utils/computation.ts b/src/utils/computation.ts
index 9619abd2f..565752b13 100644
--- a/src/utils/computation.ts
+++ b/src/utils/computation.ts
@@ -42,13 +42,20 @@ namespace Computation {
         requestAbort?: () => void
     }
 
+    export interface ProgressUpdate {
+        message?: string,
+        abort?: boolean | (() => void),
+        current?: number,
+        max?: number
+    }
+
     export interface Context {
         readonly isSynchronous: boolean,
         /** Also checks if the computation was aborted. If so, throws. */
         readonly requiresUpdate: boolean,
         requestAbort(): void,
         /** Also checks if the computation was aborted. If so, throws. */
-        updateProgress(msg: string, abort?: boolean | (() => void), current?: number, max?: number): Promise<void> | void
+        updateProgress(info: ProgressUpdate): Promise<void> | void
     }
 
     export type ProgressObserver = (progress: Readonly<Progress>) => void;
@@ -59,14 +66,14 @@ namespace Computation {
     }
 
     /** A context without updates. */
-    export const synchronousContext: Context = {
+    export const synchronous: Context = {
         isSynchronous: true,
         requiresUpdate: false,
         requestAbort() { },
-        updateProgress(msg, abort, current, max) { }
+        updateProgress(info) { }
     }
 
-    export function observableContext(params?: Partial<Params>) {
+    export function observable(params?: Partial<Params>) {
         return new ObservableContext(params);
     }
 
@@ -163,7 +170,7 @@ class ObservableContext implements Computation.Context {
         } catch (e) { }
     }
 
-    updateProgress(msg: string, abort?: boolean | (() => void), current?: number, max?: number): Promise<void> | void {
+    updateProgress({ message, abort, current, max }: Computation.ProgressUpdate): Promise<void> | void {
         this.checkAborted();
 
         const time = Computation.now();
@@ -175,14 +182,14 @@ class ObservableContext implements Computation.Context {
             this.progress.requestAbort = abort ? this.abortRequester : void 0;
         }
 
-        this.progress.message = msg;
+        if (typeof message !== 'undefined') this.progress.message = message;
         this.progress.elapsedMs = time - this.startedTime;
-        if (isNaN(current!) || isNaN(max!)) {
+        if (isNaN(current!)) {
             this.progress.isIndeterminate = true;
         } else {
             this.progress.isIndeterminate = false;
             this.progress.current = current!;
-            this.progress.max = max!;
+            if (!isNaN(max!)) this.progress.max = max!;
         }
 
         if (this.observers) {
-- 
GitLab