Compare commits
20 commits
dev
...
sock_encod
Author | SHA1 | Date | |
---|---|---|---|
|
9aa9d871b8 | ||
|
f9b98ef7e4 | ||
|
420e66842d | ||
|
7b295e4e46 | ||
|
9b8564261a | ||
|
b5e950b8a5 | ||
|
07ad16934b | ||
|
31fd1a2f01 | ||
|
d76ad45b9c | ||
|
c65da33ccd | ||
|
99d2b8273a | ||
|
ec241891fc | ||
|
80b65eb0e4 | ||
|
c6cc5bfc24 | ||
|
e8a9439b64 | ||
|
73a7cec2ed | ||
|
458c18297d | ||
|
e956d28c56 | ||
|
1486a8befa | ||
|
1eeabc2c08 |
8 changed files with 356 additions and 110 deletions
|
@ -20,7 +20,6 @@ class Build{
|
||||||
* @param {Item} weapon: Weapon that this build is using.
|
* @param {Item} weapon: Weapon that this build is using.
|
||||||
*/
|
*/
|
||||||
constructor(level, items, weapon){
|
constructor(level, items, weapon){
|
||||||
|
|
||||||
if (level < 1) { //Should these be constants?
|
if (level < 1) { //Should these be constants?
|
||||||
this.level = 1;
|
this.level = 1;
|
||||||
} else if (level > 106) {
|
} else if (level > 106) {
|
||||||
|
|
|
@ -232,79 +232,119 @@ async function parse_hash(url_tag) {
|
||||||
/* Stores the entire build in a string using B64 encoding and adds it to the URL.
|
/* Stores the entire build in a string using B64 encoding and adds it to the URL.
|
||||||
*/
|
*/
|
||||||
function encodeBuild(build, powders, skillpoints, atree, atree_state) {
|
function encodeBuild(build, powders, skillpoints, atree, atree_state) {
|
||||||
|
//currently on version 8 - a unified version for all build types using bit-level encoding
|
||||||
if (build) {
|
if (build) {
|
||||||
let build_string;
|
//final link will be [build_vers]_[len_string]_[build_string]
|
||||||
|
|
||||||
//V6 encoding - Tomes
|
|
||||||
//V7 encoding - ATree
|
|
||||||
//V8 encoding - wynn version
|
|
||||||
build_version = 8;
|
build_version = 8;
|
||||||
build_string = "";
|
let len_string = "";
|
||||||
tome_string = "";
|
let build_string = "";
|
||||||
|
let build_bits = new BitVector(0, 0);
|
||||||
|
|
||||||
|
//ITEMS
|
||||||
for (const item of build.items) {
|
for (const item of build.items) {
|
||||||
if (item.statMap.get("custom")) {
|
if (item.statMap.get("NONE") && item.statMap.get("NONE") === true) {
|
||||||
let custom = "CI-"+encodeCustom(item, true);
|
build_bits.append(0, 2); //00
|
||||||
build_string += Base64.fromIntN(custom.length, 3) + custom;
|
} else if (item.statMap.get("custom")) {
|
||||||
//build_version = Math.max(build_version, 5);
|
build_bits.append(3, 2); //11
|
||||||
|
//BitVector CI encoding TODO
|
||||||
|
|
||||||
|
// let custom = "CI-"+encodeCustom(item, true);
|
||||||
|
// build_string += Base64.fromIntN(custom.length, 3) + custom;
|
||||||
|
// build_version = Math.max(build_version, 5);
|
||||||
} else if (item.statMap.get("crafted")) {
|
} else if (item.statMap.get("crafted")) {
|
||||||
build_string += "CR-"+encodeCraft(item);
|
build_bits.append(2, 2); //10
|
||||||
} else if (item.statMap.get("category") === "tome") {
|
//BitVector CR encoding TODO
|
||||||
let tome_id = item.statMap.get("id");
|
|
||||||
if (tome_id <= 60) {
|
// build_string += "CR-"+encodeCraft(item);
|
||||||
// valid normal tome. ID 61-63 is for NONE tomes.
|
|
||||||
//build_version = Math.max(build_version, 6);
|
|
||||||
}
|
|
||||||
tome_string += Base64.fromIntN(tome_id, 2);
|
|
||||||
} else {
|
} else {
|
||||||
build_string += Base64.fromIntN(item.statMap.get("id"), 3);
|
if (item.statMap.get("category") === "tome") {
|
||||||
|
//we will encode tomes later
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
build_bits.append(1, 2); //01
|
||||||
|
build_bits.append(item.statMap.get("id"), 13);
|
||||||
|
|
||||||
|
//powderable
|
||||||
|
if (powderable_keys.includes(item.statMap.get("type"))) {
|
||||||
|
if (item.statMap.get("powders") && item.statMap.get("powders").length !== 0) {
|
||||||
|
//has powders
|
||||||
|
build_bits.append(1, 1);
|
||||||
|
|
||||||
|
//num of powders in 8 bits, then each powder (6 bits)
|
||||||
|
//Having more than 256 powders on a vanilla item is NOT HANDLED.
|
||||||
|
build_bits.append(item.statMap.get("powders").length, 8);
|
||||||
|
for (const powder of item.statMap.get("powders")) {
|
||||||
|
build_bits.append(powder, 6);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//no powders
|
||||||
|
build_bits.append(0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const skp of skillpoints) {
|
//SKILL POINTS
|
||||||
build_string += Base64.fromIntN(skp, 2); // Maximum skillpoints: 2048
|
|
||||||
}
|
|
||||||
build_string += Base64.fromIntN(build.level, 2);
|
|
||||||
for (const _powderset of powders) {
|
|
||||||
let n_bits = Math.ceil(_powderset.length / 6);
|
|
||||||
build_string += Base64.fromIntN(n_bits, 1); // Hard cap of 378 powders.
|
|
||||||
// Slice copy.
|
|
||||||
let powderset = _powderset.slice();
|
|
||||||
while (powderset.length != 0) {
|
|
||||||
let firstSix = powderset.slice(0,6).reverse();
|
|
||||||
let powder_hash = 0;
|
|
||||||
for (const powder of firstSix) {
|
|
||||||
powder_hash = (powder_hash << 5) + 1 + powder; // LSB will be extracted first.
|
|
||||||
}
|
|
||||||
build_string += Base64.fromIntN(powder_hash, 5);
|
|
||||||
powderset = powderset.slice(6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
build_string += tome_string;
|
|
||||||
|
|
||||||
|
//the original schema included a flag to indicate whether or not skill points are included.
|
||||||
|
//any reason for having a flag isn't implemented yet, so for now every build will have the skill point flag set.
|
||||||
|
build_bits.append(1, 1);
|
||||||
|
|
||||||
|
for (const skp of build.base_skillpoints) {
|
||||||
|
build_bits.append(skp, 8); // Maximum skillpoints: 255 (allows for manual assign up to 150)
|
||||||
|
}
|
||||||
|
|
||||||
|
//BUILD LEVEL
|
||||||
|
|
||||||
|
// [flag to indicate if level is not 106 (0/1)]
|
||||||
|
// [else: level (7 bits, allows for lv 1->127)]
|
||||||
|
if (player_build.level != 106) {
|
||||||
|
build_bits.append(1, 1);
|
||||||
|
build_bits.append(player_build.level, 7);
|
||||||
|
} else {
|
||||||
|
build_bits.append(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TOMES
|
||||||
|
|
||||||
|
// [flag to indicate if tomes are included (0/1)]
|
||||||
|
// [if set: 7 sequential tome IDs, each 6 bits unsigned]
|
||||||
|
if (build.tomes.length > 0) {
|
||||||
|
build_bits.append(1, 1);
|
||||||
|
//decoding will assume that tomes has length of 7.
|
||||||
|
for (const tome of build.tomes) {
|
||||||
|
build_bits.append(tome.id, 6);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
build_bits.append(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ATREE
|
||||||
|
|
||||||
|
// [flag to indicate if atree data is present]
|
||||||
|
// [atree data: see existing encoding impl] //idk the impl
|
||||||
if (atree.length > 0 && atree_state.get(atree[0].ability.id).active) {
|
if (atree.length > 0 && atree_state.get(atree[0].ability.id).active) {
|
||||||
//build_version = Math.max(build_version, 7);
|
build_bits.append(1, 1);
|
||||||
const bitvec = encode_atree(atree, atree_state);
|
const atree_bitvec = encode_atree(atree, atree_state);
|
||||||
build_string += bitvec.toB64();
|
build_bits.append(atree_bitvec);
|
||||||
|
} else {
|
||||||
|
build_bits.append(0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return build_version.toString() + "_" + build_string;
|
//compute length and return final build hash
|
||||||
|
return build_version.toString() + "_" + len_string + "_" + build_string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_full_url() {
|
|
||||||
return `${url_base}?v=${wynn_version_id.toString()}${location.hash}`
|
|
||||||
}
|
|
||||||
|
|
||||||
function copyBuild() {
|
function copyBuild() {
|
||||||
copyTextToClipboard(get_full_url());
|
copyTextToClipboard(url_base+location.hash);
|
||||||
document.getElementById("copy-button").textContent = "Copied!";
|
document.getElementById("copy-button").textContent = "Copied!";
|
||||||
}
|
}
|
||||||
|
|
||||||
function shareBuild(build) {
|
function shareBuild(build) {
|
||||||
if (build) {
|
if (build) {
|
||||||
let text = get_full_url()+"\n"+
|
let text = url_base+location.hash+"\n"+
|
||||||
"WynnBuilder build:\n"+
|
"WynnBuilder build:\n"+
|
||||||
"> "+build.items[0].statMap.get("displayName")+"\n"+
|
"> "+build.items[0].statMap.get("displayName")+"\n"+
|
||||||
"> "+build.items[1].statMap.get("displayName")+"\n"+
|
"> "+build.items[1].statMap.get("displayName")+"\n"+
|
||||||
|
@ -314,13 +354,7 @@ function shareBuild(build) {
|
||||||
"> "+build.items[5].statMap.get("displayName")+"\n"+
|
"> "+build.items[5].statMap.get("displayName")+"\n"+
|
||||||
"> "+build.items[6].statMap.get("displayName")+"\n"+
|
"> "+build.items[6].statMap.get("displayName")+"\n"+
|
||||||
"> "+build.items[7].statMap.get("displayName")+"\n"+
|
"> "+build.items[7].statMap.get("displayName")+"\n"+
|
||||||
"> "+build.items[15].statMap.get("displayName")+" ["+build_powders[4].map(x => powderNames.get(x)).join("")+"]\n";
|
"> "+build.items[15].statMap.get("displayName")+" ["+build_powders[4].map(x => powderNames.get(x)).join("")+"]";
|
||||||
for (let tomeslots = 8; tomeslots < 15; tomeslots++) {
|
|
||||||
if (!build.items[tomeslots].statMap.has('NONE')) {
|
|
||||||
text += ">"+' (Has Tomes)' ;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
copyTextToClipboard(text);
|
copyTextToClipboard(text);
|
||||||
document.getElementById("share-button").textContent = "Copied!";
|
document.getElementById("share-button").textContent = "Copied!";
|
||||||
}
|
}
|
||||||
|
|
|
@ -428,7 +428,7 @@ class BuildAssembleNode extends ComputeNode {
|
||||||
if (all_none && !location.hash) {
|
if (all_none && !location.hash) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new Build(level, equipments, weapon);
|
return new Build(level, equipments, tomes, weapon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
140
js/utils.js
140
js/utils.js
|
@ -172,7 +172,13 @@ Base64 = (function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (typeof data === "number") {
|
} else if (typeof data === "number") {
|
||||||
if (typeof length === "undefined")
|
if (typeof length === "undefined") {
|
||||||
|
if (data == 0) {
|
||||||
|
length = 0;
|
||||||
|
} else {
|
||||||
|
length = Math.ceil(Math.log(data + 1) / Math.log(2)); //+1 to account for powers of 2
|
||||||
|
}
|
||||||
|
}
|
||||||
if (length < 0) {
|
if (length < 0) {
|
||||||
throw new RangeError("BitVector must have nonnegative length.");
|
throw new RangeError("BitVector must have nonnegative length.");
|
||||||
}
|
}
|
||||||
|
@ -189,6 +195,10 @@ Base64 = (function () {
|
||||||
throw new TypeError("BitVector must be instantiated with a Number or a B64 String");
|
throw new TypeError("BitVector must be instantiated with a Number or a B64 String");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bit_vec.length == 0) {
|
||||||
|
bit_vec = [0];
|
||||||
|
}
|
||||||
|
|
||||||
this.length = length;
|
this.length = length;
|
||||||
this.bits = new Uint32Array(bit_vec);
|
this.bits = new Uint32Array(bit_vec);
|
||||||
}
|
}
|
||||||
|
@ -201,7 +211,7 @@ Base64 = (function () {
|
||||||
*/
|
*/
|
||||||
read_bit(idx) {
|
read_bit(idx) {
|
||||||
if (idx < 0 || idx >= this.length) {
|
if (idx < 0 || idx >= this.length) {
|
||||||
throw new RangeError("Cannot read bit outside the range of the BitVector. ("+idx+" > "+this.length+")");
|
throw new RangeError("Cannot read bit outside the range of the BitVector. ("+idx+" >= "+this.length+")");
|
||||||
}
|
}
|
||||||
return ((this.bits[Math.floor(idx / 32)] & (1 << idx)) == 0 ? 0 : 1);
|
return ((this.bits[Math.floor(idx / 32)] & (1 << idx)) == 0 ? 0 : 1);
|
||||||
}
|
}
|
||||||
|
@ -311,46 +321,51 @@ Base64 = (function () {
|
||||||
|
|
||||||
/** Appends data to the BitVector.
|
/** Appends data to the BitVector.
|
||||||
*
|
*
|
||||||
* @param {Number | String} data - The data to append.
|
* @param {Number | String | BitVector} data - The data to append.
|
||||||
* @param {Number} length - The length, in bits, of the new data. This is ignored if data is a string.
|
* @param {Number} length - The length, in bits, of the new data. This is ignored if data is a string. Defaults to 32 for numbers.
|
||||||
*/
|
*/
|
||||||
append(data, length) {
|
append(data, length = 32) {
|
||||||
if (length < 0) {
|
if (length < 0) {
|
||||||
throw new RangeError("BitVector length must increase by a nonnegative number.");
|
throw new RangeError("BitVector length must increase by a nonnegative number.");
|
||||||
}
|
}
|
||||||
|
|
||||||
let bit_vec = [];
|
//actual new data length is needed for resizing purposes
|
||||||
for (const uint of this.bits) {
|
|
||||||
bit_vec.push(uint);
|
|
||||||
}
|
|
||||||
if (typeof data === "string") {
|
if (typeof data === "string") {
|
||||||
let int = bit_vec[bit_vec.length - 1];
|
|
||||||
let bv_idx = this.length;
|
|
||||||
length = data.length * 6;
|
length = data.length * 6;
|
||||||
let updated_curr = false;
|
} else if (data instanceof BitVector) {
|
||||||
for (let i = 0; i < data.length; i++) {
|
length = data.length;
|
||||||
let char = Base64.toInt(data[i]);
|
|
||||||
let pre_pos = bv_idx % 32;
|
|
||||||
int |= (char << bv_idx);
|
|
||||||
bv_idx += 6;
|
|
||||||
let post_pos = bv_idx % 32;
|
|
||||||
if (post_pos < pre_pos) { //we have to have filled up the integer
|
|
||||||
if (bit_vec.length == this.bits.length && !updated_curr) {
|
|
||||||
bit_vec[bit_vec.length - 1] = int;
|
|
||||||
updated_curr = true;
|
|
||||||
} else {
|
|
||||||
bit_vec.push(int);
|
|
||||||
}
|
|
||||||
int = (char >>> (6 - post_pos));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == data.length - 1) {
|
let new_length = this.length + length;
|
||||||
if (bit_vec.length == this.bits.length && !updated_curr) {
|
if (this.bits.length * this.bits.BYTES_PER_ELEMENT * 8 < new_length) {
|
||||||
bit_vec[bit_vec.length - 1] = int;
|
//resize the internal repr by a factor of 2 before recursive calling
|
||||||
} else if (post_pos != 0) {
|
let bit_vec = Array(2 * this.bits.length).fill(0);
|
||||||
bit_vec.push(int);
|
for (let i = 0; i < this.bits.length; i++) {
|
||||||
|
bit_vec[i] = this.bits[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.bits = new Uint32Array(bit_vec);
|
||||||
|
return this.append(data, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//just write to the original bitvec
|
||||||
|
let curr_idx = Math.floor(this.length / 32);
|
||||||
|
let pos = this.length;
|
||||||
|
|
||||||
|
if (typeof data === "string") {
|
||||||
|
//daily reminder that shifts are modded by 32
|
||||||
|
for (const character of data) {
|
||||||
|
let char = Base64.toInt(character);
|
||||||
|
this.bits[curr_idx] |= (char << pos);
|
||||||
|
|
||||||
|
//if we go to the "next" char, update it
|
||||||
|
if (Math.floor(pos / 32) < Math.floor((pos + 5) / 32)) {
|
||||||
|
this.bits[curr_idx + 1] |= (char >>> (6 - (pos + 6) % 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
//update counters
|
||||||
|
pos += 6;
|
||||||
|
curr_idx = Math.floor(pos / 32);
|
||||||
}
|
}
|
||||||
} else if (typeof data === "number") {
|
} else if (typeof data === "number") {
|
||||||
//convert to int just in case
|
//convert to int just in case
|
||||||
|
@ -362,15 +377,36 @@ Base64 = (function () {
|
||||||
}
|
}
|
||||||
//could be split between multiple new ints
|
//could be split between multiple new ints
|
||||||
//reminder that shifts implicitly mod 32
|
//reminder that shifts implicitly mod 32
|
||||||
bit_vec[bit_vec.length - 1] |= ((int & ~((~0) << length)) << (this.length));
|
if (length == 32) {
|
||||||
if (((this.length - 1) % 32 + 1) + length > 32) {
|
this.bits[curr_idx] |= int << (this.length);
|
||||||
bit_vec.push(int >>> (32 - this.length));
|
} else {
|
||||||
|
this.bits[curr_idx] |= ((int & ~((~0) << length)) << (this.length));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//overflow part
|
||||||
|
if ((pos % 32) + length > 32) {
|
||||||
|
this.bits[curr_idx + 1] = (int >>> (32 - this.length));
|
||||||
|
}
|
||||||
|
} else if (data instanceof BitVector) {
|
||||||
|
//fill to end of curr int of existing bv
|
||||||
|
let other_pos = (32 - (pos % 32));
|
||||||
|
this.bits[curr_idx] |= data.slice(0, other_pos);
|
||||||
|
curr_idx += 1;
|
||||||
|
|
||||||
|
//fill full ints
|
||||||
|
while (other_pos + 32 < data.length) {
|
||||||
|
this.bits[curr_idx] = data.slice(other_pos, other_pos + 32);
|
||||||
|
curr_idx += 1;
|
||||||
|
other_pos += 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
//fill from "rest of" length/bv
|
||||||
|
this.bits[curr_idx] = data.slice(other_pos, data.length);
|
||||||
} else {
|
} else {
|
||||||
throw new TypeError("BitVector must be appended with a Number or a B64 String");
|
throw new TypeError("BitVector must be appended with a Number or a B64 String");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bits = new Uint32Array(bit_vec);
|
//update length
|
||||||
this.length += length;
|
this.length += length;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -661,6 +697,9 @@ const getScript = url => new Promise((resolve, reject) => {
|
||||||
/*
|
/*
|
||||||
GENERIC TEST FUNCTIONS
|
GENERIC TEST FUNCTIONS
|
||||||
*/
|
*/
|
||||||
|
const TEST_SUCCESS = 1;
|
||||||
|
const TEST_FAIL = 0;
|
||||||
|
|
||||||
/** The generic assert function. Fails on all "false-y" values. Useful for non-object equality checks, boolean value checks, and existence checks.
|
/** The generic assert function. Fails on all "false-y" values. Useful for non-object equality checks, boolean value checks, and existence checks.
|
||||||
*
|
*
|
||||||
* @param {*} arg - argument to assert.
|
* @param {*} arg - argument to assert.
|
||||||
|
@ -668,8 +707,10 @@ GENERIC TEST FUNCTIONS
|
||||||
*/
|
*/
|
||||||
function assert(arg, msg) {
|
function assert(arg, msg) {
|
||||||
if (!arg) {
|
if (!arg) {
|
||||||
throw new Error(msg ? msg : "Assert failed.");
|
console.trace(msg ? msg : "Assert failed.");
|
||||||
|
return TEST_FAIL;
|
||||||
}
|
}
|
||||||
|
return TEST_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Asserts object equality of the 2 parameters. For loose and strict asserts, use assert().
|
/** Asserts object equality of the 2 parameters. For loose and strict asserts, use assert().
|
||||||
|
@ -680,8 +721,10 @@ GENERIC TEST FUNCTIONS
|
||||||
*/
|
*/
|
||||||
function assert_equals(arg1, arg2, msg) {
|
function assert_equals(arg1, arg2, msg) {
|
||||||
if (!Object.is(arg1, arg2)) {
|
if (!Object.is(arg1, arg2)) {
|
||||||
throw new Error(msg ? msg : "Assert Equals failed. " + arg1 + " is not " + arg2 + ".");
|
console.trace(msg ? msg : "Assert Equals failed. " + arg1 + " is not " + arg2 + ".");
|
||||||
|
return TEST_FAIL;
|
||||||
}
|
}
|
||||||
|
return TEST_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Asserts object inequality of the 2 parameters. For loose and strict asserts, use assert().
|
/** Asserts object inequality of the 2 parameters. For loose and strict asserts, use assert().
|
||||||
|
@ -692,8 +735,10 @@ function assert_equals(arg1, arg2, msg) {
|
||||||
*/
|
*/
|
||||||
function assert_not_equals(arg1, arg2, msg) {
|
function assert_not_equals(arg1, arg2, msg) {
|
||||||
if (Object.is(arg1, arg2)) {
|
if (Object.is(arg1, arg2)) {
|
||||||
throw new Error(msg ? msg : "Assert Not Equals failed. " + arg1 + " is " + arg2 + ".");
|
console.trace(msg ? msg : "Assert Not Equals failed. " + arg1 + " is " + arg2 + ".");
|
||||||
|
return TEST_FAIL;
|
||||||
}
|
}
|
||||||
|
return TEST_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Asserts proximity between 2 arguments. Should be used for any floating point datatype.
|
/** Asserts proximity between 2 arguments. Should be used for any floating point datatype.
|
||||||
|
@ -705,8 +750,10 @@ function assert_equals(arg1, arg2, msg) {
|
||||||
*/
|
*/
|
||||||
function assert_near(arg1, arg2, epsilon = 1E-5, msg) {
|
function assert_near(arg1, arg2, epsilon = 1E-5, msg) {
|
||||||
if (Math.abs(arg1 - arg2) > epsilon) {
|
if (Math.abs(arg1 - arg2) > epsilon) {
|
||||||
throw new Error(msg ? msg : "Assert Near failed. " + arg1 + " is not within " + epsilon + " of " + arg2 + ".");
|
console.trace(msg ? msg : "Assert Near failed. " + arg1 + " is not within " + epsilon + " of " + arg2 + ".");
|
||||||
|
return TEST_FAIL;
|
||||||
}
|
}
|
||||||
|
return TEST_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Asserts that the input argument is null.
|
/** Asserts that the input argument is null.
|
||||||
|
@ -716,8 +763,10 @@ function assert_near(arg1, arg2, epsilon = 1E-5, msg) {
|
||||||
*/
|
*/
|
||||||
function assert_null(arg, msg) {
|
function assert_null(arg, msg) {
|
||||||
if (arg !== null) {
|
if (arg !== null) {
|
||||||
throw new Error(msg ? msg : "Assert Near failed. " + arg + " is not null.");
|
console.trace(msg ? msg : "Assert Near failed. " + arg + " is not null.");
|
||||||
|
return TEST_FAIL;
|
||||||
}
|
}
|
||||||
|
return TEST_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Asserts that the input argument is undefined.
|
/** Asserts that the input argument is undefined.
|
||||||
|
@ -727,8 +776,10 @@ function assert_null(arg, msg) {
|
||||||
*/
|
*/
|
||||||
function assert_undefined(arg, msg) {
|
function assert_undefined(arg, msg) {
|
||||||
if (arg !== undefined) {
|
if (arg !== undefined) {
|
||||||
throw new Error(msg ? msg : "Assert Near failed. " + arg + " is not undefined.");
|
console.trace(msg ? msg : "Assert Near failed. " + arg + " is not undefined.");
|
||||||
|
return TEST_FAIL;
|
||||||
}
|
}
|
||||||
|
return TEST_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Asserts that there is an error when a callback function is run.
|
/** Asserts that there is an error when a callback function is run.
|
||||||
|
@ -740,9 +791,10 @@ function assert_error(func_binding, msg) {
|
||||||
try {
|
try {
|
||||||
func_binding();
|
func_binding();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return;
|
return TEST_SUCCESS;
|
||||||
}
|
}
|
||||||
throw new Error(msg ? msg : "Function didn't throw an error.");
|
console.trace(msg ? msg : "Function didn't throw an error.");
|
||||||
|
return TEST_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -779,8 +831,6 @@ function deepcopy(obj, refs=undefined) {
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
11
temp.py
Normal file
11
temp.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import base64
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="Do a little trolling.")
|
||||||
|
parser.add_argument('infile', help='input file to read data from')
|
||||||
|
parser.add_argument('outfile', help='output file to dump clean data into')
|
||||||
|
args = parser.parse_args()
|
||||||
|
infile, outfile = args.infile, args.outfile
|
32
testing/index.html
Normal file
32
testing/index.html
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<!-- This is supposed to be a testing page. Modify it as you need. -->
|
||||||
|
|
||||||
|
<html scroll-behavior="smooth">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>WynnBuilder Dev</title>
|
||||||
|
<link rel="icon" href="../media/icons/new/atlas64.png">
|
||||||
|
<link rel="manifest" href="manifest.json">
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=.45, user-scalable=no">
|
||||||
|
|
||||||
|
<!-- nunito font, copying wynnbuilder, which is copying wynndata -->
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Nunito&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Nunito&display=swap" rel="stylesheet">
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||||
|
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="../css/sq2bs.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body id = "body" class = "all">
|
||||||
|
<!-- add DOM elements as desired -->
|
||||||
|
|
||||||
|
<!-- add scripts -->
|
||||||
|
<script type="text/javascript" src="../js/utils.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
26
unit_tests/index.html
Normal file
26
unit_tests/index.html
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<body>
|
||||||
|
<head>
|
||||||
|
<meta name="HandheldFriendly" content="true" />
|
||||||
|
<meta name="MobileOptimized" content="320" />
|
||||||
|
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, width=device-width, user-scalable=no" />
|
||||||
|
<!-- nunito font, copying wynndata -->
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=.45, user-scalable=no">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Nunito&display=swap" rel="stylesheet">
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="../css/sq2bs.css">
|
||||||
|
<link rel="icon" href="../media/icons/new/builder.png">
|
||||||
|
<link rel="manifest" href="manifest.json">
|
||||||
|
<title>WynnBuilder</title>
|
||||||
|
</head>
|
||||||
|
<div>
|
||||||
|
Scram kid this page ain't for you
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript" src = "./test_main.js"></script>
|
||||||
|
<!--Import other needed scripts here-->
|
||||||
|
<script type="text/javascript" src="../js/utils.js"></script>
|
||||||
|
<!--script type="text/javascript" src="../js/builder/optimize.js"></script-->
|
||||||
|
</body>
|
94
unit_tests/test_main.js
Normal file
94
unit_tests/test_main.js
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
|
||||||
|
|
||||||
|
//requires js/utils.js
|
||||||
|
function test_bv() {
|
||||||
|
/* BASIC TESTS - NO EDGE CASES */
|
||||||
|
//empty array
|
||||||
|
let bv = new BitVector(0);
|
||||||
|
console.log(bv.toB64()); //0
|
||||||
|
bv.append(10, 4);
|
||||||
|
console.log(bv.toB64()); //A
|
||||||
|
bv.append(10, 4);
|
||||||
|
console.log(bv.toB64(), bv.bits); //g2, 170 (0b10 101010)
|
||||||
|
|
||||||
|
bv = new BitVector("");
|
||||||
|
console.log(bv.toB64(), bv.bits, bv.length);
|
||||||
|
bv.append("A");
|
||||||
|
console.log(bv.toB64(), bv.bits); //A
|
||||||
|
bv.append("102");
|
||||||
|
console.log(bv.toB64(), bv.bits); //A102
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//make sure extra length doesn't do anything
|
||||||
|
bv = new BitVector(0);
|
||||||
|
bv.append(10, 5);
|
||||||
|
console.log(bv.toB64()); //A
|
||||||
|
bv.append(10, 4);
|
||||||
|
console.log(bv.toB64(), bv.bits); //a5, 330 (0b101 001010)
|
||||||
|
|
||||||
|
//non-empty array
|
||||||
|
bv = new BitVector(32); //100000
|
||||||
|
console.log(bv.toB64(), bv.bits); //W, 32 (0b 100000)
|
||||||
|
bv.append(1, 1);
|
||||||
|
console.log(bv.toB64(), bv.bits); //W1, 96 (0b 1 100000)
|
||||||
|
bv.append(10, 4);
|
||||||
|
console.log(bv.toB64(), bv.bits); //WL, 1376 (0b 10101 100000)
|
||||||
|
|
||||||
|
bv = new BitVector(7, 2);
|
||||||
|
bv.append("ABCDE");
|
||||||
|
console.log(bv.toB64(), bv.bits, bv.length); // limqu0, 0b 00 111000 110100 110000 101100 101111
|
||||||
|
|
||||||
|
//bit ops
|
||||||
|
console.log(bv.read_bit(7)); //0
|
||||||
|
bv.set_bit(7);
|
||||||
|
console.log(bv.read_bit(7)); //1
|
||||||
|
console.log(bv.toB64(), bv.bits); //WN , 1504 (0b 10111 100000)
|
||||||
|
bv.clear_bit(7);
|
||||||
|
console.log(bv.read_bit(7)); //0
|
||||||
|
|
||||||
|
|
||||||
|
/* SIMPLE EDGE CASE TESTS*/
|
||||||
|
|
||||||
|
// string -> 3 ints
|
||||||
|
bv = new BitVector("a1s2d3f4A9XJKw-m");
|
||||||
|
console.log(bv.toB64(), bv.bits, bv.length);
|
||||||
|
bv.append("M+LKeoxZJ0JELW0x");
|
||||||
|
console.log(bv.toB64(), bv.bits, bv.length);
|
||||||
|
|
||||||
|
|
||||||
|
//full int
|
||||||
|
bv = new BitVector(4294967295);
|
||||||
|
console.log(bv.toB64(), bv.bits, bv.length); //-----3, 4294967295, (0b 11 111111 111111 111111 111111 111111)
|
||||||
|
|
||||||
|
//append single bit to full int
|
||||||
|
bv.append(1, 1);
|
||||||
|
console.log(bv.toB64(), bv.bits, bv.length); //-----7, [4294967295, 1], (0b 111 1s...)
|
||||||
|
|
||||||
|
|
||||||
|
//append full int to full int to full int
|
||||||
|
bv = new BitVector(4294967295);
|
||||||
|
bv.append(4294967280);
|
||||||
|
console.log(bv.toB64(), bv.bits, bv.length); // -----3----F, [4294967295, 4294967280], (0b 1111 1....1 000011 111111 ...)
|
||||||
|
bv.append(4294967167);
|
||||||
|
console.log(bv.toB64(), bv.bits, bv.length); // -----3-----V----, [4294967295, 4294967280, 4294967167, 0] (0b 1...1 011111 1....1 000011 111111)
|
||||||
|
|
||||||
|
|
||||||
|
/* BIG TESTS */
|
||||||
|
bv = new BitVector(12341234); //(0b 101111 000100 111111 110010)
|
||||||
|
console.log(bv.toB64(), bv.bits, bv.length); // o-4l, 12341234 (0b 101111 000100 111111 110010)
|
||||||
|
console.log(bv.slice(10, 15)); //19 (100 11)
|
||||||
|
bv.append(4113241323); //(0b 11 110101 001010 110001 010011 101011)
|
||||||
|
bv.append(2213461274); //(0b 1000 001111 101110 101111 010001 1010)
|
||||||
|
bv.append(1273491384); //(0b 10010 111110 011111 101111 101110 00)
|
||||||
|
bv.append(1828394744); //(0b 110110 011111 011000 101101 111100 0)
|
||||||
|
bv.append(1938417329); //(0b 1 110011 100010 011110 011010 110001)
|
||||||
|
console.log(bv.toB64(), bv.bits, bv.length); //o -4lhJn ArhHlk F8klV+ IuRn+i 5hv9E7
|
||||||
|
|
||||||
|
bv = new BitVector("");
|
||||||
|
bv_2 = new BitVector("a1s2d3f4A9XJKw-m");
|
||||||
|
console.log(bv_2.toB64(), bv_2.bits, bv_2.length);
|
||||||
|
bv.append(bv_2);
|
||||||
|
console.log(bv.toB64(), bv.bits, bv.length);
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue