Skip to content
This repository was archived by the owner on Mar 21, 2024. It is now read-only.

Commit

Permalink
traverse and swap
Browse files Browse the repository at this point in the history
  • Loading branch information
Erin Schnabel committed Nov 18, 2018
1 parent 0039f3b commit b307b11
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 111 deletions.
2 changes: 1 addition & 1 deletion manualCompare.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ if ( process.argv.length >= 4 ) {
fs.writeFileSync('./result.manualCompareOne.json', JSON.stringify(result, null, 2));
});
} else {
new SweepActions().compareAll().then((result) => {
new SweepActions({debug: true}).compareAll().then((result) => {
fs.writeFileSync('./result.manualCompareAll.json', JSON.stringify(result, null, 2));
});
}
Expand Down
8 changes: 2 additions & 6 deletions manualTraverse.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,7 @@ const SweepActions = require('./src/SweepActions.js');
const util = require('util');
const fs = require('fs');

debug = true;

new SweepActions().traverse().filter((x) => {
let filter = ! ( debug );
return filter ? (x.status && x.status.indexOf('ok') < 0) : true;
}).then((result) => {
new SweepActions({debug: true}).traverse().then((result) => {
fs.writeFileSync('./result.manualTraverse.json', JSON.stringify(result, null, 2));
});

61 changes: 32 additions & 29 deletions src/ScoreBook.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,13 @@ class ScoreBook {
}

getScores() {
return this.scoreDb.view('scores', 'all_scores');
return this.scoreDb.view('scores', 'all_scores')
.then((view) => { return view.rows; });
}

getPaths(){
return this.scoreDb.view('scores', 'by_path')
.then((view) => { return view.rows; });
}

/*
Expand All @@ -146,10 +152,11 @@ class ScoreBook {
* when we're done. We're relying on _many subsequent
* invocations to eventually get sites sorted-ish.
*/
findSiteSwaps(all_scores) {
findSiteSwaps(all_scores, paths) {
// Filter out firstRoom and rooms with unassigned/null values
let scores = all_scores.filter(elem => elem.id !== 'firstroom' );
// Scores come back: [ { id: id, key: score, value: path }, ... ]
// Paths are the opposite [ { id: id, key: path, value: score }, .. ]

// keep track of rooms eligible for swapping
let swap_eligible = {};
Expand All @@ -159,6 +166,7 @@ class ScoreBook {

let result = {
swaps: [],
longest_path: (paths[paths.length - 1].key),
high: (scores[scores.length - 1].key),
low: 0,
median: 0,
Expand All @@ -169,16 +177,17 @@ class ScoreBook {

// iterate by ascending score..
for(let i = 0; i < scores.length; i++) {
let score1 = scores[i];
let score = scores[i];


// ignore empty rooms when calculating stats
if ( result.median === 0 && score1.key >= 0 ) {
console.log("low score", i, score1);
result.low = score1.key; // first non-empty room
result.non_empty = scores.length - i +1;
console.log("scores.length", scores.length);
if ( result.median === 0 && score.key >= 0 ) {
console.log("low score", i, score);
console.log("first non-empty i", i);
result.non_empty = scores.length - i +1;
console.log("number of non-empty rooms", result.non_empty);
result.low = score.key; // first non-empty room
console.log("scores.length", scores.length);

let median_x = Math.floor(result.non_empty / 2) + i;
let quart_x = Math.floor(result.non_empty / 4);
Expand All @@ -193,29 +202,23 @@ class ScoreBook {
}

// if this score is still eligible for swapping, then..
if ( !!swap_eligible[score1.id] ) {
// iterate from high score to low score: favor big jumps
for(let j = scores.length - 1; j >= 0; j--) {
let score2 = scores[j];
if ( !!swap_eligible[score.id] ) {
//console.log(`****: [${i}] ${score.key} ${score.value}`);
// Iterate by paths: lower paths are closer to the center
for(let j = 1; j < paths.length; j++) {
let path = paths[j];

if ( score1.key >= score2.key ) {
// done with this. We're now looking at scores smaller than ours.
//console.log(`LAST: [${i}] ${score1.key} ${score1.value} --> [${j}] ${score2.key} ${score2.value} -- ${score1.id}, ${score2.id}`);
break;
} else if ( !swap_eligible[score2.id] ) {
continue;
} else if ( score1.value === score2.value ) {
//console.log(`SKIP: [${i}] ${score1.key} ${score1.value} --> [${j}] ${score2.key} ${score2.value} -- ${score1.id}, ${score2.id}`);
if ( score.id === path.id || score.value === path.key ) {
continue;
} else if ( score1.value < score2.value ) {
console.log(`SWAP: [${i}] ${score1.key} ${score1.value} <-- [${j}] ${score2.key} ${score2.value} -- ${score1.id}, ${score2.id}`);
// remove scores from eligibility
delete swap_eligible[score1.id];
delete swap_eligible[score2.id];
result.swaps.push([score1, score2]);
break;
} else {
//console.log(`????: [${i}] ${score1.key} ${score1.value} --> [${j}] ${score2.key} ${score2.value} -- ${score1.id}, ${score2.id}`);
} else if ( !!swap_eligible[path.id] ) {
if ( score.value < path.key && score.key < path.value ) {
console.log(`SWAP: [${i}] ${score.key}pts ${score.value} <-- ${path.value}pts ${path.key} -- ${score.id}, ${path.id}`);
delete swap_eligible[score.id];
delete swap_eligible[path.id];
result.swaps.push([{id: score.id, path: score.value, score: score.key},
{id: path.id, path: path.key, score: path.value}]);
break;
}
}
}
}
Expand Down
17 changes: 3 additions & 14 deletions src/SlackNotification.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,12 @@ class SlackNotification {
this.channel = '#sweep';
}

scoreStart() {
scoring(count) {
let body = {
username: 'Evaluator',
icon_emoji: ':sleuth_or_spy:',
channel: this.channel,
text: 'Off to do the rounds...'
};

return offItGoes(body, this.slack_url, this.env);
}

scoreEnd(count) {
let body = {
username: 'Evaluator',
icon_emoji: ':sleuth_or_spy:',
channel: this.channel,
text: `Tallied scores for ${count} rooms`
text: `Tallying scores for ${count} rooms`
};

return offItGoes(body, this.slack_url, this.env);
Expand Down Expand Up @@ -108,7 +97,7 @@ class SlackNotification {
swap(text) {
let body = {
username: 'Permutare',
icon_emoji: ':revolving_hearts:',
icon_emoji: ':dizzy:',
channel: this.channel,
text: text
};
Expand Down
112 changes: 53 additions & 59 deletions src/SweepActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,20 +61,15 @@ class SweepActions {
assert.ok(this.params.invoke, 'Specify action to invoke');

switch(this.params.invoke) {
case 'scoreAll': // (1) no parameters
return this.scoreAll();
case 'evaluate': // (1a) requires site to evaluate
return this.evaluate();
case 'compareAll': // (2) requires no parameters
return this.compareAll();
case 'swap': // (2a) requires two sites to swap
return this.swap();
case 'traverse': // (3) no parameters
return this.traverse();
case 'orphans': // (3a) requires list of known sites
return this.orphans();
case 'holes': // (3b) requires list of known sites
return this.holes();
case 'traverseSwap':
return this.traverse()
.then((result1) => {
return this.compareAll()
.then((result2) => Promise.resolve({
traverse: result1,
compare: result2
}));
});
default:
throw new Error(`Unkown invoke target ${this.params.invoke}`);
}
Expand All @@ -85,9 +80,6 @@ class SweepActions {
.then((all_sites) => {
let action_list = [];

// notify that we're starting..
action_list.push(this.slack.scoreStart());

// kick off a new asynchronous action for each site
for(let i = 0; i < all_sites.length; i++ ) {
let px = JSON.parse(JSON.stringify(this.params)); // copy / prevent mutation
Expand All @@ -99,7 +91,7 @@ class SweepActions {

// Note how many actions
action_list.unshift(Promise.resolve({status: `${action_list.length} actions`}));
action_list.push(this.slack.scoreEnd(action_list.length));
action_list.push(this.slack.scoring(action_list.length));

return Promise.all(action_list);
})
Expand Down Expand Up @@ -144,32 +136,34 @@ class SweepActions {
compareAll() {
return this.scorebook.getScores()
.then((all_scores) => {
console.log(all_scores);
let action_list = [];
let stats = this.scorebook.findSiteSwaps(all_scores.rows);
console.log(stats);

action_list.push(this.slack.swapStats(
`All sorted. Out of ${stats.non_empty} rooms: \n`
+ ` :+1: The high score was ${stats.high}\n`
+ ` :ok_hand: The third quartile score was ${stats.third_quartile}\n`
+ ` :v: The median score was ${stats.median}\n`
+ ` :point_up: The first quartile score was ${stats.first_quartile}\n`
+ ` :-1: The low score was ${stats.low}\n`
));

for (let i = 0; i < stats.swaps.length; i++) {
let px = JSON.parse(JSON.stringify(this.params)); // copy / prevent mutation
px.compare = {
a: stats.swaps[i][0],
b: stats.swaps[i][1]
};
action_list.push(action(this.ow, this.env, 'sweep/actionCompare', px, this.compare(px.compare.a, px.compare.b)));
}
return this.scorebook.getPaths()
.then((all_paths) => {
let action_list = [];
let stats = this.scorebook.findSiteSwaps(all_scores, all_paths);

action_list.push(this.slack.swapStats(
`All sorted. Out of ${stats.non_empty} rooms: \n`
+ ` :+1: The high score was ${stats.high}\n`
+ ` :ok_hand: The third quartile score was ${stats.third_quartile}\n`
+ ` :v: The median score was ${stats.median}\n`
+ ` :point_up: The first quartile score was ${stats.first_quartile}\n`
+ ` :-1: The low score was ${stats.low}\n`
+ ` :running: The longest path is ${stats.longest_path}`
));

for (let i = 0; i < stats.swaps.length; i++) {
let px = JSON.parse(JSON.stringify(this.params)); // copy / prevent mutation
px.compare = {
a: stats.swaps[i][0],
b: stats.swaps[i][1]
};
action_list.push(action(this.ow, this.env, 'sweep/actionCompare', px, this.compare(px.compare.a, px.compare.b)));
}

// Note how many actions
action_list.unshift(Promise.resolve({status: `${action_list.length} actions`}));
return Promise.all(action_list);
// Note how many actions
action_list.unshift(Promise.resolve({status: `${action_list.length} actions`}));
return Promise.all(action_list);
});
})
.then((result) => { return this.filterResult(result); })
.then((result) => Promise.resolve({
Expand All @@ -189,34 +183,34 @@ class SweepActions {
assert.ok(a && b, 'Specify two sites to swap');

return this.mapClient.fetch(a.id)
.then((site_1) => {
a.site = site_1;
a.path = Math.abs(site_1.coord.x) + Math.abs(site_1.coord.y);
if ( a.value !== a.path ) {
.then((a_site) => {
a.site = a_site;
let path = Math.abs(a.site.coord.x) + Math.abs(a.site.coord.y);
if ( path !== a.path ) {
return Promise.resolve({ id: a.id, status: 'compare-ok', skip: true,
msg: `SKIPPED: ${a.value} != ${a.path} for ${a.id}` });
msg: `SKIPPED: ${path} != ${a.path} for ${a.id}` });
}
return this.mapClient.fetch(b.id)
.then((site_2) => {
b.site = site_2;
b.path = Math.abs(site_2.coord.x) + Math.abs(site_2.coord.y);
if ( b.value !== b.path ) {
.then((b_site) => {
b.site = b_site;
let path = Math.abs(b.site.coord.x) + Math.abs(b.site.coord.y);
if ( path !== b.path ) {
return Promise.resolve({ id: b.id, status: 'compare-ok', skip: true,
msg: `SKIPPED: ${b.value} != ${b.path} for ${b.id}` });
msg: `SKIPPED: ${path} != ${b.path} for ${b.id}` });
}

let a_name = !!a.site.info ? a.site.info.name : a.id;
let b_name = !!b.site.info ? b.site.info.name : b.id;
let msg = `${a_name}[score=${a.key}/path=${a.value}] swapped with ${b_name}[score=${b.key}/path=${b.value}]`;
let msg = `${a_name}[score=${a.score}/path=${a.path}] swapped with ${b_name}[score=${b.score}/path=${b.path}]`;

return Promise.try(() => {
// if ( this.env === 'production' ) {
// return this.mapClient.swap_sites(a.site, b.site);
// } else {
if ( this.env !== 'unittest' ) {
return this.mapClient.swap_sites(a.site, b.site);
} else {
return Promise.resolve([a.site, b.site]);
// }
}
})
//.then(() => this.slack.swap(msg))
.then(() => this.slack.swap(msg))
.then(() => Promise.resolve({
marker: this.params.marker,
status: 'swap-ok',
Expand Down
7 changes: 5 additions & 2 deletions src/actionInvoke.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@
const SweepActions = require('./SweepActions.js');

function invoke (params) {
params = params || {};
params.invoke = params.invoke || 'traverseSwap';
return new SweepActions(params).invoke()
.then((result) => {
return { payload: result };
.catch((err) => {
console.log("error", JSON.stringify(err));
throw err;
});
}

Expand Down

0 comments on commit b307b11

Please sign in to comment.