Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inherit scores for "Don't know" and "Don't care" #42

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/data/dataFileNames.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"main":"firstModule.json","others":["RfEsZpNK.791f2cda554d18a95fc3734bbe65f88b.json","sArkxak3.bda40d280ffd6baa48d38117905bd5ab.json","2qVqSwId.6c0be3e0610de0d44ac1b294da16d4fd.json","vQrgRbIS.80594ce9bebcfa2809538046c647dde3.json","U77gcZNf.8857dc7179e0813487e12b85611b3b9b.json","RqGMsFtz.aeed2715e184fe51657af9db9ba6f965.json"]}
{"main":"firstModule.json","others":["RfEsZpNK.791f2cda554d18a95fc3734bbe65f88b.json","sArkxak3.bda40d280ffd6baa48d38117905bd5ab.json","2qVqSwId.b86995173d611d4e9c0524bce3ecf6e5.json","vQrgRbIS.80594ce9bebcfa2809538046c647dde3.json","U77gcZNf.8857dc7179e0813487e12b85611b3b9b.json","RqGMsFtz.aeed2715e184fe51657af9db9ba6f965.json"]}
122 changes: 105 additions & 17 deletions app/data/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
ANALYTICS_STRINGS,
EVENTS,
SCORES,
INHERITED_KEYS,
} from '../utils/constants';
import logTiming from '../utils/logTiming';

Expand Down Expand Up @@ -99,6 +100,14 @@ const store = {
});
},

computeInheritRule(newScoreKey, oldScoreKey) {
if (INHERITED_KEYS.includes(newScoreKey)) {
return [(item) => true, newScoreKey];
} else if (INHERITED_KEYS.includes(oldScoreKey)) {
return [(item) => item.scoreKey === oldScoreKey, SCORES.LEVEL_0.key];
}
},

getItem(idOrItem) {
if (typeof idOrItem === `string`) {
return this.itemCache[idOrItem];
Expand Down Expand Up @@ -197,20 +206,25 @@ const store = {

Object.assign(item, data); // gasp, mutability

if (saveToDisk) {
diskStore.setItem(item.id, data);
}

if (!updateDom) return;

const nextItemState = serializeItemState(item);
this.updateItemDom(item, prevItemState !== nextItemState, scoreChanged, options);
},

updateItemDom(item, renderItem, renderScore, options = {}) {
// potentially trigger a re-render of the item
if (item.visible && prevItemState !== nextItemState) {
if (item.visible && renderItem) {
this.triggerListener(item.id); // TODO (davidg): `ROW-${item.id}`
}

// potentially trigger a re-render of the score bar
if (scoreChanged) {
if (saveToDisk) diskStore.setItem(item.id, data);

if (this.selectedItem && this.selectedItem.id === idOrItem.id) {
if (renderScore) {
if (this.selectedItem && this.selectedItem.id === item.id) {
this.triggerListener(EVENTS.SCORE_CHANGED); // updates the score bar
}
}
Expand All @@ -221,15 +235,56 @@ const store = {
if (!item) return;
const updateDom = (typeof options.updateDom !== `undefined`) ? options.updateDom : true;

const oldScoreKey = item.scoreKey;

// caution: update the score summary before updating the item
const updatedItems = this.updateScoreSummary(item, scoreKey, item.scoreKey);
const updatedItems = this.updateScoreSummary(item, scoreKey, oldScoreKey);

this.updateItem(item, { scoreKey }, options);

const inheritRule = this.computeInheritRule(scoreKey, oldScoreKey);

if (inheritRule) {
const dirtyChildren = [];

const updateChildren = (parent, test) => {
const children = this.getChildrenOf(parent.id);
if (!children) return;

children.forEach((child) => {
if (test(child)) {
dirtyChildren.push(child);
}

updateChildren(child, test);
});
};

updateChildren(item, inheritRule[0]);

const optionsNoDom = Object.assign({}, options);
optionsNoDom.updateDom = false;

const updateChild = (child) => {
this.updateItem(child, { scoreKey: inheritRule[1] }, optionsNoDom);
};
const updateChildDom = (child) => {
this.updateItemDom(child, true, true, options);
};

dirtyChildren.forEach(updateChild);

const visibleChildren = dirtyChildren.filter((child) => child.visible);
visibleChildren.forEach(updateChildDom);
}

if (updateDom) {
updatedItems.forEach((updatedItem) => {
const updateItem = (updatedItem) => {
this.triggerListener(`PIE-${updatedItem.id}`);
});
};

const visibleItems = updatedItems.filter((item) => item.visible);
visibleItems.forEach(updateItem);
}
},

Expand All @@ -241,23 +296,56 @@ const store = {
oldScoreKey = oldScoreKey || SCORES.LEVEL_0.key;
const updatedItems = [];

const updateParentScore = (child) => {
const parent = this.getParent(child);
if (!parent) return; // we're at the top
const updateSummary = (parent, inheritRule) => {
const children = this.getChildrenOf(parent.id);
if (!children) return; // we're at the bottom
updatedItems.push(parent);

this.scoreSummary[parent.id] = this.scoreSummary[parent.id] || {};
this.scoreSummary[parent.id][newScoreKey] = this.scoreSummary[parent.id][newScoreKey] || 0;
this.scoreSummary[parent.id][newScoreKey] += 1;
Object.keys(SCORES).forEach((scoreKey) => {
this.scoreSummary[parent.id][scoreKey] = children
.map((child) => {
this.scoreSummary[child.id] = this.scoreSummary[child.id] || {};
const scoreSummary = this.scoreSummary[child.id][scoreKey] || 0;
let newValue = child.scoreKey || SCORES.LEVEL_0.key;

if (child === item) {
newValue = newScoreKey;
} else if (inheritRule) {
if (inheritRule[0](child)) {
newValue = inheritRule[1];
}
}

return newValue === scoreKey ? scoreSummary + 1 : scoreSummary;
})
.reduce((a, b) => a + b, 0);
});
};
const updateChildrenScore = (parent, inheritRule) => {
const children = this.getChildrenOf(parent.id);
if (!children) return; // we're at the bottom

if (!newItem) {
this.scoreSummary[parent.id][oldScoreKey] -= 1;
}
children.forEach((child) => {
updateChildrenScore(child, inheritRule);
});

updateSummary(parent, inheritRule);
};
const updateParentScore = (child) => {
const parent = this.getParent(child);
if (!parent) return; // we're at the top

updateSummary(parent);
updateParentScore(parent);
};

// we don't update the item directly, only its ancestors
const inheritRule = this.computeInheritRule(newScoreKey, oldScoreKey);

if (inheritRule) {
updateChildrenScore(item, inheritRule);
}

updateParentScore(item);

return updatedItems;
Expand Down
2 changes: 2 additions & 0 deletions app/utils/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ export const SCORES = {
},
};

export const INHERITED_KEYS = [SCORES.LEVEL_1.key, SCORES.LEVEL_4.key];

export const KEYS = {
DOWN: 40,
ENTER: 13,
Expand Down