Skip to content

Commit

Permalink
update topsheet to handle new threading model
Browse files Browse the repository at this point in the history
  • Loading branch information
billyc committed Dec 9, 2021
1 parent 2587521 commit 057edcc
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 82 deletions.
53 changes: 39 additions & 14 deletions src/components/TopSheet/TopSheet.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@

<script lang="ts">
import { FileSystemConfig } from '@/Globals'
import { Worker, spawn, Thread } from 'threads'
import { Vue, Component, Watch, Prop } from 'vue-property-decorator'
import TopSheetWorker from './TopSheetWorker.worker.ts?worker'
export type TableRow = {
title: string
value: any
Expand Down Expand Up @@ -47,6 +48,7 @@ export default class VueComponent extends Vue {
private formattedValue(value: any) {
if (!isNaN(value)) return value.toLocaleString([this.$store.state.locale, 'en'])
if (value === undefined) return '-?-'
return value
}
Expand All @@ -58,7 +60,7 @@ export default class VueComponent extends Vue {
private beforeDestroy() {
try {
if (this.solverThread) {
Thread.terminate(this.solverThread)
this.solverThread.terminate()
this.solverThread = null
}
} catch (e) {
Expand All @@ -69,31 +71,35 @@ export default class VueComponent extends Vue {
private async boxChanged() {
console.log('changed!')
if (this.solverThread) {
const output = await this.solverThread.updateCalculations(this.entries)
this.table = output
this.solverThread.postMessage({
command: 'updateCalculations',
entries: this.entries,
})
}
}
private async runTopSheet() {
if (!this.files.length) return
if (!this.solverThread) {
console.log('spawing topsheet thread')
this.solverThread = await spawn(new Worker('./TopSheetWorker.thread'))
}
try {
this.table = await this.solverThread.runTopSheet({
if (!this.solverThread) {
console.log('spawning topsheet thread')
this.solverThread = new TopSheetWorker()
this.solverThread.onmessage = (message: MessageEvent) => {
this.processWorkerMessage(message)
}
}
this.solverThread.postMessage({
command: 'runTopSheet',
fileSystemConfig: this.fileSystemConfig,
subfolder: this.subfolder,
files: this.files,
yaml: this.yaml,
})
this.title = await this.solverThread.getTitle(this.$store.state.locale)
const outputRows = await this.solverThread.getTextEntryFields()
this.entries = outputRows
this.solverThread.postMessage({ command: 'getTitle', locale: this.$store.state.locale })
this.solverThread.postMessage({ command: 'getTextEntryFields' })
} catch (e) {
const message = '' + e
console.log(message)
Expand All @@ -102,6 +108,25 @@ export default class VueComponent extends Vue {
}
this.$emit('isLoaded')
}
private processWorkerMessage(message: MessageEvent) {
console.log(message)
const data = message.data
switch (data.response) {
case 'title':
this.title = data.title
break
case 'entries':
this.entries = data.entryFields
break
case 'results':
this.table = data.results
break
default:
// shouldn't be here
console.error(data)
}
}
}
</script>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
// named *thread* because *worker* gets processed by webpack already

/*eslint prefer-rest-params: "off"*/

import { expose } from 'threads/worker'
import nerdamer, { ExpressionParam } from 'nerdamer'
import pako from 'pako'
import Papaparse from 'papaparse'
import YAML from 'yaml'
import { parseNumbers } from 'xml2js/lib/processors'

import { FileSystemConfig } from '@/Globals'
import HTTPFileSystem from '@/js/HTTPFileSystem'
Expand All @@ -34,6 +30,30 @@ type TopsheetYaml = {
outputs: { title?: string; title_en?: string; title_de?: string; value: any; style?: any }[]
}

onmessage = async function (message) {
const data = message.data
switch (data.command) {
case 'getTitle':
const title = getTitle(data.locale)
postMessage({ response: 'title', title })
break
case 'getTextEntryFields':
const entryFields = getTextEntryFields()
postMessage({ response: 'entries', entryFields })
break
case 'runTopSheet':
const outputs = await runTopSheet(data)
postMessage({ response: 'results', results: outputs })
break
case 'updateCalculations':
const update = await updateCalculations(data.entries)
postMessage({ response: 'results', results: update })
break
default:
console.error('Strange command:', data)
}
}

// global variables
let _fileSystem: HTTPFileSystem
let _subfolder = ''
Expand All @@ -53,81 +73,79 @@ const testRows: TableRow[] = [
{ title: 'Rating', value: '⭐️⭐️⭐️' },
]

expose({
async updateCalculations(entries: { key: string; title: string; value: any }[]) {
const boxes: any = {}
async function updateCalculations(entries: { key: string; title: string; value: any }[]) {
const boxes: any = {}

for (const box of entries) boxes[box.key] = box.value
for (const box of entries) boxes[box.key] = box.value

_boxValues = boxes
_boxValues = boxes

// do all calculations, in order they are written.
_calculations = doAllCalculations()
const outputs = buildOutputs()
return outputs
},
// do all calculations, in order they are written.
_calculations = doAllCalculations()
const outputs = buildOutputs()
return outputs
}

getTitle(locale: string) {
console.log('getTitle locale', locale)
let title = ''
function getTitle(locale: string) {
console.log('getTitle locale', locale)
let title = ''

if (locale === 'en') title = _yaml.title_en || _yaml.title || _yaml.title_de || ''
else title = _yaml.title_de || _yaml.title || _yaml.title_en || ''
if (locale === 'en') title = _yaml.title_en || _yaml.title || _yaml.title_de || ''
else title = _yaml.title_de || _yaml.title || _yaml.title_en || ''

return title
},
return title
}

getTextEntryFields() {
const boxes = _yaml.userEntries
if (!boxes) return []
function getTextEntryFields() {
const boxes = _yaml.userEntries
if (!boxes) return []

const fields: any[] = []
const locale = globalStore.state.locale
const fields: any[] = []
const locale = globalStore.state.locale

for (const key of Object.keys(boxes)) {
const box = boxes[key]
for (const key of Object.keys(boxes)) {
const box = boxes[key]

let title = ''
if (locale === 'en') title = box.title_en || box.title || box.title_de || key
else title = box.title_de || box.title || box.title_en || key
let title = ''
if (locale === 'en') title = box.title_en || box.title || box.title_de || key
else title = box.title_de || box.title || box.title_en || key

fields.push({ key, title, value: _calculations[key] })
}
return fields
},

async runTopSheet(props: {
fileSystemConfig: FileSystemConfig
subfolder: string
files: string[]
yaml: string
}) {
// console.log('TopSheet thread worker starting')

_fileSystem = new HTTPFileSystem(props.fileSystemConfig)
_subfolder = props.subfolder
_files = props.files
_yamlFile = props.yaml

// read the table definitions from yaml
_yaml = await getYaml()

// load all files
await loadFiles()
console.log(_fileData)

// set up user entry boxes if first run
if (!Object.keys(_boxValues).length) {
console.log('** resetting boxvalues')
_boxValues = getBoxValues(_yaml)
}
fields.push({ key, title, value: _calculations[key] })
}
return fields
}

// do all calculations, in order they are written.
_calculations = doAllCalculations()
const outputs = buildOutputs()
return outputs
},
})
async function runTopSheet(props: {
fileSystemConfig: FileSystemConfig
subfolder: string
files: string[]
yaml: string
}) {
// console.log('TopSheet thread worker starting')

_fileSystem = new HTTPFileSystem(props.fileSystemConfig)
_subfolder = props.subfolder
_files = props.files
_yamlFile = props.yaml

// read the table definitions from yaml
_yaml = await getYaml()

// load all files
await loadFiles()
console.log(_fileData)

// set up user entry boxes if first run
if (!Object.keys(_boxValues).length) {
console.log('** resetting boxvalues')
_boxValues = getBoxValues(_yaml)
}

// do all calculations, in order they are written.
_calculations = doAllCalculations()
const outputs = buildOutputs()
return outputs
}

// ----- helper functions ------------------------------------------------

Expand Down Expand Up @@ -392,3 +410,10 @@ async function loadFileOrGzipFile(filename: string) {
return buffer
}
}

function parseNumbers(str: any) {
if (!isNaN(str)) {
str = str % 1 === 0 ? parseInt(str, 10) : parseFloat(str)
}
return str
}
6 changes: 5 additions & 1 deletion src/views/DashBoard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,12 @@ export default class VueComponent extends Vue {
}
private getCardStyle(card: any) {
// figure out height. If card has registered a resizer with changeDimensions(),
// then it needs a default height (300)
const defaultHeight = this.resizers[card.id] ? 300 : undefined
const height = card.height ? card.height * 60 : defaultHeight
const flex = card.width || 1
const height = card.height ? card.height * 60 : 300
let style: any = {
margin: '2rem 3rem 2rem 0',
Expand Down

0 comments on commit 057edcc

Please sign in to comment.