BitVector fixes w/ unit tests + unit testing page (/unit_tests/)
This commit is contained in:
parent
420e66842d
commit
f9b98ef7e4
4 changed files with 163 additions and 168 deletions
|
@ -4,6 +4,37 @@ let build_powders;
|
|||
function getItemNameFromID(id) { return idMap.get(id); }
|
||||
function getTomeNameFromID(id) { return tomeIDMap.get(id); }
|
||||
|
||||
function parsePowdering(powder_info) {
|
||||
// TODO: Make this run in linear instead of quadratic time... ew
|
||||
let powdering = [];
|
||||
for (let i = 0; i < 5; ++i) {
|
||||
let powders = "";
|
||||
let n_blocks = Base64.toInt(powder_info.charAt(0));
|
||||
// console.log(n_blocks + " blocks");
|
||||
powder_info = powder_info.slice(1);
|
||||
for (let j = 0; j < n_blocks; ++j) {
|
||||
let block = powder_info.slice(0,5);
|
||||
let six_powders = Base64.toInt(block);
|
||||
for (let k = 0; k < 6 && six_powders != 0; ++k) {
|
||||
powders += powderNames.get((six_powders & 0x1f) - 1);
|
||||
six_powders >>>= 5;
|
||||
}
|
||||
powder_info = powder_info.slice(5);
|
||||
}
|
||||
powdering[i] = powders;
|
||||
}
|
||||
return [powdering, powder_info];
|
||||
}
|
||||
|
||||
let atree_data = null;
|
||||
const wynn_version_names = [
|
||||
'2.0.1.1',
|
||||
'2.0.1.2'
|
||||
];
|
||||
const WYNN_VERSION_LATEST = wynn_version_names.length - 1;
|
||||
// Default to the newest version.
|
||||
let wynn_version_id = WYNN_VERSION_LATEST;
|
||||
|
||||
/*
|
||||
* Populate fields based on url, and calculate build.
|
||||
* TODO: THIS CODE IS GOD AWFUL result of being lazy
|
||||
|
@ -193,154 +224,6 @@ async function parse_hash(url_tag) {
|
|||
}
|
||||
}
|
||||
|
||||
function parsePowdering(powder_info) {
|
||||
// TODO: Make this run in linear instead of quadratic time... ew
|
||||
let powdering = [];
|
||||
for (let i = 0; i < 5; ++i) {
|
||||
let powders = "";
|
||||
let n_blocks = Base64.toInt(powder_info.charAt(0));
|
||||
// console.log(n_blocks + " blocks");
|
||||
powder_info = powder_info.slice(1);
|
||||
for (let j = 0; j < n_blocks; ++j) {
|
||||
let block = powder_info.slice(0,5);
|
||||
let six_powders = Base64.toInt(block);
|
||||
for (let k = 0; k < 6 && six_powders != 0; ++k) {
|
||||
powders += powderNames.get((six_powders & 0x1f) - 1);
|
||||
six_powders >>>= 5;
|
||||
}
|
||||
powder_info = powder_info.slice(5);
|
||||
}
|
||||
powdering[i] = powders;
|
||||
}
|
||||
return [powdering, powder_info];
|
||||
}
|
||||
|
||||
let atree_data = null;
|
||||
|
||||
/*
|
||||
* Populate fields based on url, and calculate build.
|
||||
*/
|
||||
function decodeBuild(url_tag) {
|
||||
if (url_tag) {
|
||||
//default values
|
||||
let equipment = [null, null, null, null, null, null, null, null, null];
|
||||
let tomes = [null, null, null, null, null, null, null];
|
||||
let powdering = ["", "", "", "", ""];
|
||||
let info = url_tag.split("_");
|
||||
let version = info[0];
|
||||
let save_skp = false;
|
||||
let skillpoints = [0, 0, 0, 0, 0];
|
||||
let level = 106;
|
||||
|
||||
let version_number = parseInt(version)
|
||||
//equipment (items)
|
||||
// TODO: use filters
|
||||
if (version_number < 4) {
|
||||
let equipments = info[1];
|
||||
for (let i = 0; i < 9; ++i ) {
|
||||
let equipment_str = equipments.slice(i*3,i*3+3);
|
||||
equipment[i] = getItemNameFromID(Base64.toInt(equipment_str));
|
||||
}
|
||||
info[1] = equipments.slice(27);
|
||||
}
|
||||
else if (version_number == 4) {
|
||||
let info_str = info[1];
|
||||
let start_idx = 0;
|
||||
for (let i = 0; i < 9; ++i ) {
|
||||
if (info_str.charAt(start_idx) === "-") {
|
||||
equipment[i] = "CR-"+info_str.slice(start_idx+1, start_idx+18);
|
||||
start_idx += 18;
|
||||
}
|
||||
else {
|
||||
let equipment_str = info_str.slice(start_idx, start_idx+3);
|
||||
equipment[i] = getItemNameFromID(Base64.toInt(equipment_str));
|
||||
start_idx += 3;
|
||||
}
|
||||
}
|
||||
info[1] = info_str.slice(start_idx);
|
||||
}
|
||||
else if (version_number <= 7) {
|
||||
let info_str = info[1];
|
||||
let start_idx = 0;
|
||||
for (let i = 0; i < 9; ++i ) {
|
||||
if (info_str.slice(start_idx,start_idx+3) === "CR-") {
|
||||
equipment[i] = info_str.slice(start_idx, start_idx+20);
|
||||
start_idx += 20;
|
||||
} else if (info_str.slice(start_idx+3,start_idx+6) === "CI-") {
|
||||
let len = Base64.toInt(info_str.slice(start_idx,start_idx+3));
|
||||
equipment[i] = info_str.slice(start_idx+3,start_idx+3+len);
|
||||
start_idx += (3+len);
|
||||
} else {
|
||||
let equipment_str = info_str.slice(start_idx, start_idx+3);
|
||||
equipment[i] = getItemNameFromID(Base64.toInt(equipment_str));
|
||||
start_idx += 3;
|
||||
}
|
||||
}
|
||||
info[1] = info_str.slice(start_idx);
|
||||
}
|
||||
//constant in all versions
|
||||
for (let i in equipment) {
|
||||
setValue(equipment_inputs[i], equipment[i]);
|
||||
}
|
||||
|
||||
//level, skill point assignments, and powdering
|
||||
if (version_number == 1) {
|
||||
let powder_info = info[1];
|
||||
let res = parsePowdering(powder_info);
|
||||
powdering = res[0];
|
||||
} else if (version_number == 2) {
|
||||
save_skp = true;
|
||||
let skillpoint_info = info[1].slice(0, 10);
|
||||
for (let i = 0; i < 5; ++i ) {
|
||||
skillpoints[i] = Base64.toIntSigned(skillpoint_info.slice(i*2,i*2+2));
|
||||
}
|
||||
|
||||
let powder_info = info[1].slice(10);
|
||||
let res = parsePowdering(powder_info);
|
||||
powdering = res[0];
|
||||
} else if (version_number <= 7){
|
||||
level = Base64.toInt(info[1].slice(10,12));
|
||||
setValue("level-choice",level);
|
||||
save_skp = true;
|
||||
let skillpoint_info = info[1].slice(0, 10);
|
||||
for (let i = 0; i < 5; ++i ) {
|
||||
skillpoints[i] = Base64.toIntSigned(skillpoint_info.slice(i*2,i*2+2));
|
||||
}
|
||||
|
||||
let powder_info = info[1].slice(12);
|
||||
|
||||
let res = parsePowdering(powder_info);
|
||||
powdering = res[0];
|
||||
info[1] = res[1];
|
||||
}
|
||||
// Tomes.
|
||||
if (version >= 6 && version < 8) {
|
||||
//tome values do not appear in anything before v6.
|
||||
for (let i in tomes) {
|
||||
let tome_str = info[1].charAt(i);
|
||||
let tome_name = getTomeNameFromID(Base64.toInt(tome_str));
|
||||
setValue(tomeInputs[i], tome_name);
|
||||
}
|
||||
info[1] = info[1].slice(7);
|
||||
}
|
||||
|
||||
if (version == 7) {
|
||||
// ugly af. only works since its the last thing. will be fixed with binary decode
|
||||
atree_data = new BitVector(info[1]);
|
||||
}
|
||||
else {
|
||||
atree_data = null;
|
||||
}
|
||||
|
||||
for (let i in powder_inputs) {
|
||||
setValue(powder_inputs[i], powdering[i]);
|
||||
}
|
||||
for (let i in skillpoints) {
|
||||
setValue(skp_order[i] + "-skp", skillpoints[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Stores the entire build in a string using B64 encoding and adds it to the URL.
|
||||
*/
|
||||
function encodeBuild(build, powders, skillpoints, atree, atree_state) {
|
||||
|
|
28
js/utils.js
28
js/utils.js
|
@ -176,7 +176,7 @@ Base64 = (function () {
|
|||
if (data == 0) {
|
||||
length = 0;
|
||||
} else {
|
||||
length = Math.ceil(Math.log(data) / Math.log(2));
|
||||
length = Math.ceil(Math.log(data + 1) / Math.log(2)); //+1 to account for powers of 2
|
||||
}
|
||||
}
|
||||
if (length < 0) {
|
||||
|
@ -211,7 +211,7 @@ Base64 = (function () {
|
|||
*/
|
||||
read_bit(idx) {
|
||||
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);
|
||||
}
|
||||
|
@ -377,13 +377,19 @@ Base64 = (function () {
|
|||
}
|
||||
//could be split between multiple new ints
|
||||
//reminder that shifts implicitly mod 32
|
||||
if (length == 32) {
|
||||
this.bits[curr_idx] |= int << (this.length);
|
||||
} else {
|
||||
this.bits[curr_idx] |= ((int & ~((~0) << length)) << (this.length));
|
||||
if (((this.length - 1) % 32 + 1) + length > 32) {
|
||||
}
|
||||
|
||||
//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)) % 32;
|
||||
let other_pos = (32 - (pos % 32));
|
||||
this.bits[curr_idx] |= data.slice(0, other_pos);
|
||||
curr_idx += 1;
|
||||
|
||||
|
@ -405,18 +411,6 @@ Base64 = (function () {
|
|||
}
|
||||
};
|
||||
|
||||
function test_bv() {
|
||||
//empty array
|
||||
let bv = new BitVector(0);
|
||||
bv.append(10, 4);
|
||||
console.log(bv);
|
||||
|
||||
bv = new BitVector(0);
|
||||
bv.append(10, 5);
|
||||
console.log(bv);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Turns a raw stat and a % stat into a final stat on the basis that - raw and >= 100% becomes 0 and + raw and <=-100% becomes negative.
|
||||
|
@ -1054,5 +1048,3 @@ if (screen.width < 992) {
|
|||
scrollPos = document.documentElement.scrollTop;
|
||||
});
|
||||
}
|
||||
|
||||
test_bv();
|
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