finst version done, no steps tho
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
1268
Cargo.lock
generated
Normal file
1268
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "simplex_web"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
web-sys = { version = "0.3.80", features = ["console"] }
|
||||||
|
yew = { version = "0.21.0", features = ["csr"] }
|
||||||
332
dist/index.html
vendored
Normal file
332
dist/index.html
vendored
Normal file
@@ -0,0 +1,332 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Simplex Optimizer</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100vh;
|
||||||
|
background: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Top input section */
|
||||||
|
.input-section {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
padding: 20px;
|
||||||
|
gap: 20px;
|
||||||
|
background: #ffffff;
|
||||||
|
border-bottom: 2px solid #dee2e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-box {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: #f1f3f5;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 15px;
|
||||||
|
box-shadow: 0 2px 5px rgba(0,0,0,0.05);
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-box h2 {
|
||||||
|
margin: 0 0 10px 0;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: #343a40;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-section {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-section h3 {
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
font-size: 1rem;
|
||||||
|
color: #495057;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-row input {
|
||||||
|
flex: 1;
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid #ced4da;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-row button {
|
||||||
|
padding: 8px 12px;
|
||||||
|
background: #007bff;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-row button:hover {
|
||||||
|
background: #0056b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
background: #ffffff;
|
||||||
|
padding: 6px 10px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
border: 1px solid #dee2e6;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remove-btn {
|
||||||
|
background: #dc3545;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
padding: 4px 8px;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remove-btn:hover {
|
||||||
|
background: #b02a37;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Right side objective */
|
||||||
|
.objective {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.objective input {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid #ced4da;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.objective button {
|
||||||
|
padding: 10px;
|
||||||
|
background: #28a745;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.objective button:hover {
|
||||||
|
background: #1e7e34;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bottom output section */
|
||||||
|
.output-section {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 20px;
|
||||||
|
background: #fdfdfd;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.steps {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 15px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
border: 1px solid #dee2e6;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.steps h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
color: #495057;
|
||||||
|
}
|
||||||
|
|
||||||
|
.steps ul {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.final-result {
|
||||||
|
background: #e9f7ef;
|
||||||
|
border: 1px solid #c3e6cb;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #155724;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link rel="modulepreload" href="/simplex_web-8bf72546f0e8aebd.js" crossorigin="anonymous" integrity="sha384-x4nFKfiSWzB0sCXnR6hQoO3c8Lv83ztLT8H6Lf0vfHMtRqYUsNign5AzLC+tCans"><link rel="preload" href="/simplex_web-8bf72546f0e8aebd_bg.wasm" crossorigin="anonymous" integrity="sha384-AGnm5INB9StBmD88/MSZ4spWf1Mkktyx60q0tH9gpQto4jlI9JqVHktjhhBfORAV" as="fetch" type="application/wasm"></head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
|
||||||
|
<script type="module">
|
||||||
|
import init, * as bindings from '/simplex_web-8bf72546f0e8aebd.js';
|
||||||
|
const wasm = await init({ module_or_path: '/simplex_web-8bf72546f0e8aebd_bg.wasm' });
|
||||||
|
|
||||||
|
|
||||||
|
window.wasmBindings = bindings;
|
||||||
|
|
||||||
|
|
||||||
|
dispatchEvent(new CustomEvent("TrunkApplicationStarted", {detail: {wasm}}));
|
||||||
|
|
||||||
|
</script><script>"use strict";
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
|
||||||
|
const address = '{{__TRUNK_ADDRESS__}}';
|
||||||
|
const base = '{{__TRUNK_WS_BASE__}}';
|
||||||
|
let protocol = '';
|
||||||
|
protocol =
|
||||||
|
protocol
|
||||||
|
? protocol
|
||||||
|
: window.location.protocol === 'https:'
|
||||||
|
? 'wss'
|
||||||
|
: 'ws';
|
||||||
|
const url = protocol + '://' + address + base + '.well-known/trunk/ws';
|
||||||
|
|
||||||
|
class Overlay {
|
||||||
|
constructor() {
|
||||||
|
// create an overlay
|
||||||
|
this._overlay = document.createElement("div");
|
||||||
|
const style = this._overlay.style;
|
||||||
|
style.height = "100vh";
|
||||||
|
style.width = "100vw";
|
||||||
|
style.position = "fixed";
|
||||||
|
style.top = "0";
|
||||||
|
style.left = "0";
|
||||||
|
style.backgroundColor = "rgba(222, 222, 222, 0.5)";
|
||||||
|
style.fontFamily = "sans-serif";
|
||||||
|
// not sure that's the right approach
|
||||||
|
style.zIndex = "1000000";
|
||||||
|
style.backdropFilter = "blur(1rem)";
|
||||||
|
|
||||||
|
const container = document.createElement("div");
|
||||||
|
// center it
|
||||||
|
container.style.position = "absolute";
|
||||||
|
container.style.top = "30%";
|
||||||
|
container.style.left = "15%";
|
||||||
|
container.style.maxWidth = "85%";
|
||||||
|
|
||||||
|
this._title = document.createElement("div");
|
||||||
|
this._title.innerText = "Build failure";
|
||||||
|
this._title.style.paddingBottom = "2rem";
|
||||||
|
this._title.style.fontSize = "2.5rem";
|
||||||
|
|
||||||
|
this._message = document.createElement("div");
|
||||||
|
this._message.style.whiteSpace = "pre-wrap";
|
||||||
|
|
||||||
|
const icon= document.createElement("div");
|
||||||
|
icon.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" fill="#dc3545" viewBox="0 0 16 16"><path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"/></svg>';
|
||||||
|
this._title.prepend(icon);
|
||||||
|
|
||||||
|
container.append(this._title, this._message);
|
||||||
|
this._overlay.append(container);
|
||||||
|
|
||||||
|
this._inject();
|
||||||
|
window.setInterval(() => {
|
||||||
|
this._inject();
|
||||||
|
}, 250);
|
||||||
|
}
|
||||||
|
|
||||||
|
set reason(reason) {
|
||||||
|
this._message.textContent = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
_inject() {
|
||||||
|
if (!this._overlay.isConnected) {
|
||||||
|
// prepend it
|
||||||
|
document.body?.prepend(this._overlay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Client {
|
||||||
|
constructor(url) {
|
||||||
|
this.url = url;
|
||||||
|
this.poll_interval = 5000;
|
||||||
|
this._overlay = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
const ws = new WebSocket(this.url);
|
||||||
|
ws.onmessage = (ev) => {
|
||||||
|
const msg = JSON.parse(ev.data);
|
||||||
|
switch (msg.type) {
|
||||||
|
case "reload":
|
||||||
|
this.reload();
|
||||||
|
break;
|
||||||
|
case "buildFailure":
|
||||||
|
this.buildFailure(msg.data)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ws.onclose = () => this.onclose();
|
||||||
|
}
|
||||||
|
|
||||||
|
onclose() {
|
||||||
|
window.setTimeout(
|
||||||
|
() => {
|
||||||
|
// when we successfully reconnect, we'll force a
|
||||||
|
// reload (since we presumably lost connection to
|
||||||
|
// trunk due to it being killed, so it will have
|
||||||
|
// rebuilt on restart)
|
||||||
|
const ws = new WebSocket(this.url);
|
||||||
|
ws.onopen = () => window.location.reload();
|
||||||
|
ws.onclose = () => this.onclose();
|
||||||
|
},
|
||||||
|
this.poll_interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
reload() {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
buildFailure({reason}) {
|
||||||
|
// also log the console
|
||||||
|
console.error("Build failed:", reason);
|
||||||
|
|
||||||
|
console.debug("Overlay", this._overlay);
|
||||||
|
|
||||||
|
if (!this._overlay) {
|
||||||
|
this._overlay = new Overlay();
|
||||||
|
}
|
||||||
|
this._overlay.reason = reason;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new Client(url).start();
|
||||||
|
|
||||||
|
})()
|
||||||
|
</script></body>
|
||||||
|
</html>
|
||||||
723
dist/simplex_web-8bf72546f0e8aebd.js
vendored
Normal file
723
dist/simplex_web-8bf72546f0e8aebd.js
vendored
Normal file
@@ -0,0 +1,723 @@
|
|||||||
|
let wasm;
|
||||||
|
|
||||||
|
let cachedUint8ArrayMemory0 = null;
|
||||||
|
|
||||||
|
function getUint8ArrayMemory0() {
|
||||||
|
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
|
||||||
|
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
|
||||||
|
}
|
||||||
|
return cachedUint8ArrayMemory0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );
|
||||||
|
|
||||||
|
if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); };
|
||||||
|
|
||||||
|
const MAX_SAFARI_DECODE_BYTES = 2146435072;
|
||||||
|
let numBytesDecoded = 0;
|
||||||
|
function decodeText(ptr, len) {
|
||||||
|
numBytesDecoded += len;
|
||||||
|
if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
|
||||||
|
cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );
|
||||||
|
cachedTextDecoder.decode();
|
||||||
|
numBytesDecoded = len;
|
||||||
|
}
|
||||||
|
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStringFromWasm0(ptr, len) {
|
||||||
|
ptr = ptr >>> 0;
|
||||||
|
return decodeText(ptr, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addToExternrefTable0(obj) {
|
||||||
|
const idx = wasm.__externref_table_alloc();
|
||||||
|
wasm.__wbindgen_export_2.set(idx, obj);
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleError(f, args) {
|
||||||
|
try {
|
||||||
|
return f.apply(this, args);
|
||||||
|
} catch (e) {
|
||||||
|
const idx = addToExternrefTable0(e);
|
||||||
|
wasm.__wbindgen_exn_store(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLikeNone(x) {
|
||||||
|
return x === undefined || x === null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cachedDataViewMemory0 = null;
|
||||||
|
|
||||||
|
function getDataViewMemory0() {
|
||||||
|
if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
|
||||||
|
cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
|
||||||
|
}
|
||||||
|
return cachedDataViewMemory0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getArrayJsValueFromWasm0(ptr, len) {
|
||||||
|
ptr = ptr >>> 0;
|
||||||
|
const mem = getDataViewMemory0();
|
||||||
|
const result = [];
|
||||||
|
for (let i = ptr; i < ptr + 4 * len; i += 4) {
|
||||||
|
result.push(wasm.__wbindgen_export_2.get(mem.getUint32(i, true)));
|
||||||
|
}
|
||||||
|
wasm.__externref_drop_slice(ptr, len);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
let WASM_VECTOR_LEN = 0;
|
||||||
|
|
||||||
|
const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } );
|
||||||
|
|
||||||
|
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
|
||||||
|
? function (arg, view) {
|
||||||
|
return cachedTextEncoder.encodeInto(arg, view);
|
||||||
|
}
|
||||||
|
: function (arg, view) {
|
||||||
|
const buf = cachedTextEncoder.encode(arg);
|
||||||
|
view.set(buf);
|
||||||
|
return {
|
||||||
|
read: arg.length,
|
||||||
|
written: buf.length
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
function passStringToWasm0(arg, malloc, realloc) {
|
||||||
|
|
||||||
|
if (realloc === undefined) {
|
||||||
|
const buf = cachedTextEncoder.encode(arg);
|
||||||
|
const ptr = malloc(buf.length, 1) >>> 0;
|
||||||
|
getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
|
||||||
|
WASM_VECTOR_LEN = buf.length;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
let len = arg.length;
|
||||||
|
let ptr = malloc(len, 1) >>> 0;
|
||||||
|
|
||||||
|
const mem = getUint8ArrayMemory0();
|
||||||
|
|
||||||
|
let offset = 0;
|
||||||
|
|
||||||
|
for (; offset < len; offset++) {
|
||||||
|
const code = arg.charCodeAt(offset);
|
||||||
|
if (code > 0x7F) break;
|
||||||
|
mem[ptr + offset] = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset !== len) {
|
||||||
|
if (offset !== 0) {
|
||||||
|
arg = arg.slice(offset);
|
||||||
|
}
|
||||||
|
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
|
||||||
|
const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
|
||||||
|
const ret = encodeString(arg, view);
|
||||||
|
|
||||||
|
offset += ret.written;
|
||||||
|
ptr = realloc(ptr, len, offset, 1) >>> 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WASM_VECTOR_LEN = offset;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function debugString(val) {
|
||||||
|
// primitive types
|
||||||
|
const type = typeof val;
|
||||||
|
if (type == 'number' || type == 'boolean' || val == null) {
|
||||||
|
return `${val}`;
|
||||||
|
}
|
||||||
|
if (type == 'string') {
|
||||||
|
return `"${val}"`;
|
||||||
|
}
|
||||||
|
if (type == 'symbol') {
|
||||||
|
const description = val.description;
|
||||||
|
if (description == null) {
|
||||||
|
return 'Symbol';
|
||||||
|
} else {
|
||||||
|
return `Symbol(${description})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type == 'function') {
|
||||||
|
const name = val.name;
|
||||||
|
if (typeof name == 'string' && name.length > 0) {
|
||||||
|
return `Function(${name})`;
|
||||||
|
} else {
|
||||||
|
return 'Function';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// objects
|
||||||
|
if (Array.isArray(val)) {
|
||||||
|
const length = val.length;
|
||||||
|
let debug = '[';
|
||||||
|
if (length > 0) {
|
||||||
|
debug += debugString(val[0]);
|
||||||
|
}
|
||||||
|
for(let i = 1; i < length; i++) {
|
||||||
|
debug += ', ' + debugString(val[i]);
|
||||||
|
}
|
||||||
|
debug += ']';
|
||||||
|
return debug;
|
||||||
|
}
|
||||||
|
// Test for built-in
|
||||||
|
const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
|
||||||
|
let className;
|
||||||
|
if (builtInMatches && builtInMatches.length > 1) {
|
||||||
|
className = builtInMatches[1];
|
||||||
|
} else {
|
||||||
|
// Failed to match the standard '[object ClassName]'
|
||||||
|
return toString.call(val);
|
||||||
|
}
|
||||||
|
if (className == 'Object') {
|
||||||
|
// we're a user defined class or Object
|
||||||
|
// JSON.stringify avoids problems with cycles, and is generally much
|
||||||
|
// easier than looping through ownProperties of `val`.
|
||||||
|
try {
|
||||||
|
return 'Object(' + JSON.stringify(val) + ')';
|
||||||
|
} catch (_) {
|
||||||
|
return 'Object';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// errors
|
||||||
|
if (val instanceof Error) {
|
||||||
|
return `${val.name}: ${val.message}\n${val.stack}`;
|
||||||
|
}
|
||||||
|
// TODO we could test for more things here, like `Set`s and `Map`s.
|
||||||
|
return className;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CLOSURE_DTORS = (typeof FinalizationRegistry === 'undefined')
|
||||||
|
? { register: () => {}, unregister: () => {} }
|
||||||
|
: new FinalizationRegistry(
|
||||||
|
state => {
|
||||||
|
wasm.__wbindgen_export_7.get(state.dtor)(state.a, state.b);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
function makeMutClosure(arg0, arg1, dtor, f) {
|
||||||
|
const state = { a: arg0, b: arg1, cnt: 1, dtor };
|
||||||
|
const real = (...args) => {
|
||||||
|
|
||||||
|
// First up with a closure we increment the internal reference
|
||||||
|
// count. This ensures that the Rust closure environment won't
|
||||||
|
// be deallocated while we're invoking it.
|
||||||
|
state.cnt++;
|
||||||
|
const a = state.a;
|
||||||
|
state.a = 0;
|
||||||
|
try {
|
||||||
|
return f(a, state.b, ...args);
|
||||||
|
} finally {
|
||||||
|
if (--state.cnt === 0) {
|
||||||
|
wasm.__wbindgen_export_7.get(state.dtor)(a, state.b);
|
||||||
|
CLOSURE_DTORS.unregister(state);
|
||||||
|
} else {
|
||||||
|
state.a = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
real.original = state;
|
||||||
|
CLOSURE_DTORS.register(real, state, state);
|
||||||
|
return real;
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeClosure(arg0, arg1, dtor, f) {
|
||||||
|
const state = { a: arg0, b: arg1, cnt: 1, dtor };
|
||||||
|
const real = (...args) => {
|
||||||
|
|
||||||
|
// First up with a closure we increment the internal reference
|
||||||
|
// count. This ensures that the Rust closure environment won't
|
||||||
|
// be deallocated while we're invoking it.
|
||||||
|
state.cnt++;
|
||||||
|
try {
|
||||||
|
return f(state.a, state.b, ...args);
|
||||||
|
} finally {
|
||||||
|
if (--state.cnt === 0) {
|
||||||
|
wasm.__wbindgen_export_7.get(state.dtor)(state.a, state.b); state.a = 0;
|
||||||
|
CLOSURE_DTORS.unregister(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
real.original = state;
|
||||||
|
CLOSURE_DTORS.register(real, state, state);
|
||||||
|
return real;
|
||||||
|
}
|
||||||
|
function __wbg_adapter_8(arg0, arg1, arg2) {
|
||||||
|
wasm.closure257_externref_shim(arg0, arg1, arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function __wbg_adapter_11(arg0, arg1, arg2) {
|
||||||
|
wasm.closure321_externref_shim(arg0, arg1, arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const EXPECTED_RESPONSE_TYPES = new Set(['basic', 'cors', 'default']);
|
||||||
|
|
||||||
|
async function __wbg_load(module, imports) {
|
||||||
|
if (typeof Response === 'function' && module instanceof Response) {
|
||||||
|
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
||||||
|
try {
|
||||||
|
return await WebAssembly.instantiateStreaming(module, imports);
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
const validResponse = module.ok && EXPECTED_RESPONSE_TYPES.has(module.type);
|
||||||
|
|
||||||
|
if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {
|
||||||
|
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const bytes = await module.arrayBuffer();
|
||||||
|
return await WebAssembly.instantiate(bytes, imports);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
const instance = await WebAssembly.instantiate(module, imports);
|
||||||
|
|
||||||
|
if (instance instanceof WebAssembly.Instance) {
|
||||||
|
return { instance, module };
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function __wbg_get_imports() {
|
||||||
|
const imports = {};
|
||||||
|
imports.wbg = {};
|
||||||
|
imports.wbg.__wbg_addEventListener_c8d39d7dcff00d2f = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) {
|
||||||
|
arg0.addEventListener(getStringFromWasm0(arg1, arg2), arg3, arg4);
|
||||||
|
}, arguments) };
|
||||||
|
imports.wbg.__wbg_body_3af439ac76af2afb = function(arg0) {
|
||||||
|
const ret = arg0.body;
|
||||||
|
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_bubbles_54d1d18366d19d6d = function(arg0) {
|
||||||
|
const ret = arg0.bubbles;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_cachekey_57601dac16343711 = function(arg0) {
|
||||||
|
const ret = arg0.__yew_subtree_cache_key;
|
||||||
|
return isLikeNone(ret) ? 0x100000001 : (ret) >>> 0;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_call_2f8d426a20a307fe = function() { return handleError(function (arg0, arg1) {
|
||||||
|
const ret = arg0.call(arg1);
|
||||||
|
return ret;
|
||||||
|
}, arguments) };
|
||||||
|
imports.wbg.__wbg_cancelBubble_ba3496c52eac50f9 = function(arg0) {
|
||||||
|
const ret = arg0.cancelBubble;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_childNodes_ef176b83ab95436c = function(arg0) {
|
||||||
|
const ret = arg0.childNodes;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_cloneNode_f3cc6cddf7979990 = function() { return handleError(function (arg0) {
|
||||||
|
const ret = arg0.cloneNode();
|
||||||
|
return ret;
|
||||||
|
}, arguments) };
|
||||||
|
imports.wbg.__wbg_composedPath_e3274d4b1a25887d = function(arg0) {
|
||||||
|
const ret = arg0.composedPath();
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_createElementNS_a9f53206c738878b = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) {
|
||||||
|
const ret = arg0.createElementNS(arg1 === 0 ? undefined : getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4));
|
||||||
|
return ret;
|
||||||
|
}, arguments) };
|
||||||
|
imports.wbg.__wbg_createElement_4f7fbf335b949252 = function() { return handleError(function (arg0, arg1, arg2) {
|
||||||
|
const ret = arg0.createElement(getStringFromWasm0(arg1, arg2));
|
||||||
|
return ret;
|
||||||
|
}, arguments) };
|
||||||
|
imports.wbg.__wbg_createTextNode_09ae71620b19776d = function(arg0, arg1, arg2) {
|
||||||
|
const ret = arg0.createTextNode(getStringFromWasm0(arg1, arg2));
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_document_a6efcd95d74a2ff6 = function(arg0) {
|
||||||
|
const ret = arg0.document;
|
||||||
|
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_error_3c7d958458bf649b = function(arg0, arg1) {
|
||||||
|
var v0 = getArrayJsValueFromWasm0(arg0, arg1).slice();
|
||||||
|
wasm.__wbindgen_free(arg0, arg1 * 4, 4);
|
||||||
|
console.error(...v0);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_error_7534b8e9a36f1ab4 = function(arg0, arg1) {
|
||||||
|
let deferred0_0;
|
||||||
|
let deferred0_1;
|
||||||
|
try {
|
||||||
|
deferred0_0 = arg0;
|
||||||
|
deferred0_1 = arg1;
|
||||||
|
console.error(getStringFromWasm0(arg0, arg1));
|
||||||
|
} finally {
|
||||||
|
wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_from_237b1ad767238d8b = function(arg0) {
|
||||||
|
const ret = Array.from(arg0);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_get_59c6316d15f9f1d0 = function(arg0, arg1) {
|
||||||
|
const ret = arg0[arg1 >>> 0];
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_host_e3d0174ee47b29da = function(arg0) {
|
||||||
|
const ret = arg0.host;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_insertBefore_ff3cdc8f07aee445 = function() { return handleError(function (arg0, arg1, arg2) {
|
||||||
|
const ret = arg0.insertBefore(arg1, arg2);
|
||||||
|
return ret;
|
||||||
|
}, arguments) };
|
||||||
|
imports.wbg.__wbg_instanceof_Element_96b17c2bf2f962ff = function(arg0) {
|
||||||
|
let result;
|
||||||
|
try {
|
||||||
|
result = arg0 instanceof Element;
|
||||||
|
} catch (_) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
const ret = result;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_instanceof_Event_d6f301b8e3144b40 = function(arg0) {
|
||||||
|
let result;
|
||||||
|
try {
|
||||||
|
result = arg0 instanceof Event;
|
||||||
|
} catch (_) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
const ret = result;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_instanceof_HtmlInputElement_6e301f5298c2216e = function(arg0) {
|
||||||
|
let result;
|
||||||
|
try {
|
||||||
|
result = arg0 instanceof HTMLInputElement;
|
||||||
|
} catch (_) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
const ret = result;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_instanceof_ShadowRoot_ae4bc62016938ece = function(arg0) {
|
||||||
|
let result;
|
||||||
|
try {
|
||||||
|
result = arg0 instanceof ShadowRoot;
|
||||||
|
} catch (_) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
const ret = result;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_instanceof_Window_7f29e5c72acbfd60 = function(arg0) {
|
||||||
|
let result;
|
||||||
|
try {
|
||||||
|
result = arg0 instanceof Window;
|
||||||
|
} catch (_) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
const ret = result;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_is_a001cd6ada1df292 = function(arg0, arg1) {
|
||||||
|
const ret = Object.is(arg0, arg1);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_lastChild_5847fcd93bd5162a = function(arg0) {
|
||||||
|
const ret = arg0.lastChild;
|
||||||
|
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_length_246fa1f85a0dea5b = function(arg0) {
|
||||||
|
const ret = arg0.length;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_listenerid_ed1678830a5b97ec = function(arg0) {
|
||||||
|
const ret = arg0.__yew_listener_id;
|
||||||
|
return isLikeNone(ret) ? 0x100000001 : (ret) >>> 0;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_log_f3c04200b995730f = function(arg0) {
|
||||||
|
console.log(arg0);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_namespaceURI_16a9ca763a61b64a = function(arg0, arg1) {
|
||||||
|
const ret = arg1.namespaceURI;
|
||||||
|
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||||
|
var len1 = WASM_VECTOR_LEN;
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_new_1930cbb8d9ffc31b = function() {
|
||||||
|
const ret = new Object();
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_new_8a6f238a6ece86ea = function() {
|
||||||
|
const ret = new Error();
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_newnoargs_a81330f6e05d8aca = function(arg0, arg1) {
|
||||||
|
const ret = new Function(getStringFromWasm0(arg0, arg1));
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_nextSibling_179d0a1601577aec = function(arg0) {
|
||||||
|
const ret = arg0.nextSibling;
|
||||||
|
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_outerHTML_7306ec658b1ed630 = function(arg0, arg1) {
|
||||||
|
const ret = arg1.outerHTML;
|
||||||
|
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||||
|
const len1 = WASM_VECTOR_LEN;
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_parentElement_90704850d3ceb7ee = function(arg0) {
|
||||||
|
const ret = arg0.parentElement;
|
||||||
|
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_parentNode_aa589bbf69854710 = function(arg0) {
|
||||||
|
const ret = arg0.parentNode;
|
||||||
|
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_queueMicrotask_bcc6e26d899696db = function(arg0) {
|
||||||
|
const ret = arg0.queueMicrotask;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_queueMicrotask_f24a794d09c42640 = function(arg0) {
|
||||||
|
queueMicrotask(arg0);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_removeAttribute_6930c6c8a4db23d2 = function() { return handleError(function (arg0, arg1, arg2) {
|
||||||
|
arg0.removeAttribute(getStringFromWasm0(arg1, arg2));
|
||||||
|
}, arguments) };
|
||||||
|
imports.wbg.__wbg_removeChild_3b3d6d5ab2fadc87 = function() { return handleError(function (arg0, arg1) {
|
||||||
|
const ret = arg0.removeChild(arg1);
|
||||||
|
return ret;
|
||||||
|
}, arguments) };
|
||||||
|
imports.wbg.__wbg_removeEventListener_b25c194da9564efa = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) {
|
||||||
|
arg0.removeEventListener(getStringFromWasm0(arg1, arg2), arg3, arg4 !== 0);
|
||||||
|
}, arguments) };
|
||||||
|
imports.wbg.__wbg_resolve_5775c0ef9222f556 = function(arg0) {
|
||||||
|
const ret = Promise.resolve(arg0);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_setAttribute_6a3ee9b5deb88ed3 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) {
|
||||||
|
arg0.setAttribute(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4));
|
||||||
|
}, arguments) };
|
||||||
|
imports.wbg.__wbg_set_b33e7a98099eed58 = function() { return handleError(function (arg0, arg1, arg2) {
|
||||||
|
const ret = Reflect.set(arg0, arg1, arg2);
|
||||||
|
return ret;
|
||||||
|
}, arguments) };
|
||||||
|
imports.wbg.__wbg_setcachekey_bb5f908a0e3ee714 = function(arg0, arg1) {
|
||||||
|
arg0.__yew_subtree_cache_key = arg1 >>> 0;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_setcapture_db2ee3e30ffd4878 = function(arg0, arg1) {
|
||||||
|
arg0.capture = arg1 !== 0;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_setchecked_7b7c0d2599d9cdb7 = function(arg0, arg1) {
|
||||||
|
arg0.checked = arg1 !== 0;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_setinnerHTML_fec7cc6bdfe27049 = function(arg0, arg1, arg2) {
|
||||||
|
arg0.innerHTML = getStringFromWasm0(arg1, arg2);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_setlistenerid_3d14d37a42484593 = function(arg0, arg1) {
|
||||||
|
arg0.__yew_listener_id = arg1 >>> 0;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_setnodeValue_67b8289cc9bf7650 = function(arg0, arg1, arg2) {
|
||||||
|
arg0.nodeValue = arg1 === 0 ? undefined : getStringFromWasm0(arg1, arg2);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_setpassive_ff0de39cdf5a633e = function(arg0, arg1) {
|
||||||
|
arg0.passive = arg1 !== 0;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_setsubtreeid_32b8ceff55862e29 = function(arg0, arg1) {
|
||||||
|
arg0.__yew_subtree_id = arg1 >>> 0;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_setvalue_43593e9f2309b239 = function(arg0, arg1, arg2) {
|
||||||
|
arg0.value = getStringFromWasm0(arg1, arg2);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_setvalue_ccf2650f7af384e0 = function(arg0, arg1, arg2) {
|
||||||
|
arg0.value = getStringFromWasm0(arg1, arg2);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_stack_0ed75d68575b0f3c = function(arg0, arg1) {
|
||||||
|
const ret = arg1.stack;
|
||||||
|
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||||
|
const len1 = WASM_VECTOR_LEN;
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_static_accessor_GLOBAL_1f13249cc3acc96d = function() {
|
||||||
|
const ret = typeof global === 'undefined' ? null : global;
|
||||||
|
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_static_accessor_GLOBAL_THIS_df7ae94b1e0ed6a3 = function() {
|
||||||
|
const ret = typeof globalThis === 'undefined' ? null : globalThis;
|
||||||
|
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_static_accessor_SELF_6265471db3b3c228 = function() {
|
||||||
|
const ret = typeof self === 'undefined' ? null : self;
|
||||||
|
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_static_accessor_WINDOW_16fb482f8ec52863 = function() {
|
||||||
|
const ret = typeof window === 'undefined' ? null : window;
|
||||||
|
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_subtreeid_e65dfcc52d403fd9 = function(arg0) {
|
||||||
|
const ret = arg0.__yew_subtree_id;
|
||||||
|
return isLikeNone(ret) ? 0x100000001 : (ret) >>> 0;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_target_bfb4281bfa013115 = function(arg0) {
|
||||||
|
const ret = arg0.target;
|
||||||
|
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_textContent_094fcf277dd9df42 = function(arg0, arg1) {
|
||||||
|
const ret = arg1.textContent;
|
||||||
|
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||||
|
var len1 = WASM_VECTOR_LEN;
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_then_9cc266be2bf537b6 = function(arg0, arg1) {
|
||||||
|
const ret = arg0.then(arg1);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_value_1ae15635193fdbb5 = function(arg0, arg1) {
|
||||||
|
const ret = arg1.value;
|
||||||
|
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||||
|
const len1 = WASM_VECTOR_LEN;
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_value_b3bb6dd468d1cb71 = function(arg0, arg1) {
|
||||||
|
const ret = arg1.value;
|
||||||
|
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||||
|
const len1 = WASM_VECTOR_LEN;
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_wbindgencbdrop_a85ed476c6a370b9 = function(arg0) {
|
||||||
|
const obj = arg0.original;
|
||||||
|
if (obj.cnt-- == 1) {
|
||||||
|
obj.a = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const ret = false;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_wbindgendebugstring_bb652b1bc2061b6d = function(arg0, arg1) {
|
||||||
|
const ret = debugString(arg1);
|
||||||
|
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||||
|
const len1 = WASM_VECTOR_LEN;
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_wbindgenisfunction_ea72b9d66a0e1705 = function(arg0) {
|
||||||
|
const ret = typeof(arg0) === 'function';
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_wbindgenisundefined_71f08a6ade4354e7 = function(arg0) {
|
||||||
|
const ret = arg0 === undefined;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_wbindgenthrow_4c11a24fca429ccf = function(arg0, arg1) {
|
||||||
|
throw new Error(getStringFromWasm0(arg0, arg1));
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_cast_1fd9af4f8d234577 = function(arg0, arg1) {
|
||||||
|
// Cast intrinsic for `Closure(Closure { dtor_idx: 320, function: Function { arguments: [Externref], shim_idx: 321, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
|
||||||
|
const ret = makeMutClosure(arg0, arg1, 320, __wbg_adapter_11);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_cast_2241b6af4c4b2941 = function(arg0, arg1) {
|
||||||
|
// Cast intrinsic for `Ref(String) -> Externref`.
|
||||||
|
const ret = getStringFromWasm0(arg0, arg1);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_cast_24e68085ee0f966a = function(arg0, arg1) {
|
||||||
|
// Cast intrinsic for `Closure(Closure { dtor_idx: 256, function: Function { arguments: [Ref(NamedExternref("Event"))], shim_idx: 257, ret: Unit, inner_ret: Some(Unit) }, mutable: false }) -> Externref`.
|
||||||
|
const ret = makeClosure(arg0, arg1, 256, __wbg_adapter_8);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_init_externref_table = function() {
|
||||||
|
const table = wasm.__wbindgen_export_2;
|
||||||
|
const offset = table.grow(4);
|
||||||
|
table.set(0, undefined);
|
||||||
|
table.set(offset + 0, undefined);
|
||||||
|
table.set(offset + 1, null);
|
||||||
|
table.set(offset + 2, true);
|
||||||
|
table.set(offset + 3, false);
|
||||||
|
;
|
||||||
|
};
|
||||||
|
|
||||||
|
return imports;
|
||||||
|
}
|
||||||
|
|
||||||
|
function __wbg_init_memory(imports, memory) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function __wbg_finalize_init(instance, module) {
|
||||||
|
wasm = instance.exports;
|
||||||
|
__wbg_init.__wbindgen_wasm_module = module;
|
||||||
|
cachedDataViewMemory0 = null;
|
||||||
|
cachedUint8ArrayMemory0 = null;
|
||||||
|
|
||||||
|
|
||||||
|
wasm.__wbindgen_start();
|
||||||
|
return wasm;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initSync(module) {
|
||||||
|
if (wasm !== undefined) return wasm;
|
||||||
|
|
||||||
|
|
||||||
|
if (typeof module !== 'undefined') {
|
||||||
|
if (Object.getPrototypeOf(module) === Object.prototype) {
|
||||||
|
({module} = module)
|
||||||
|
} else {
|
||||||
|
console.warn('using deprecated parameters for `initSync()`; pass a single object instead')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const imports = __wbg_get_imports();
|
||||||
|
|
||||||
|
__wbg_init_memory(imports);
|
||||||
|
|
||||||
|
if (!(module instanceof WebAssembly.Module)) {
|
||||||
|
module = new WebAssembly.Module(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
const instance = new WebAssembly.Instance(module, imports);
|
||||||
|
|
||||||
|
return __wbg_finalize_init(instance, module);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function __wbg_init(module_or_path) {
|
||||||
|
if (wasm !== undefined) return wasm;
|
||||||
|
|
||||||
|
|
||||||
|
if (typeof module_or_path !== 'undefined') {
|
||||||
|
if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
|
||||||
|
({module_or_path} = module_or_path)
|
||||||
|
} else {
|
||||||
|
console.warn('using deprecated parameters for the initialization function; pass a single object instead')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof module_or_path === 'undefined') {
|
||||||
|
module_or_path = new URL('simplex_web_bg.wasm', import.meta.url);
|
||||||
|
}
|
||||||
|
const imports = __wbg_get_imports();
|
||||||
|
|
||||||
|
if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {
|
||||||
|
module_or_path = fetch(module_or_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
__wbg_init_memory(imports);
|
||||||
|
|
||||||
|
const { instance, module } = await __wbg_load(await module_or_path, imports);
|
||||||
|
|
||||||
|
return __wbg_finalize_init(instance, module);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { initSync };
|
||||||
|
export default __wbg_init;
|
||||||
BIN
dist/simplex_web-8bf72546f0e8aebd_bg.wasm
vendored
Normal file
BIN
dist/simplex_web-8bf72546f0e8aebd_bg.wasm
vendored
Normal file
Binary file not shown.
192
index.html
Normal file
192
index.html
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Simplex Optimizer</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100vh;
|
||||||
|
background: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Top input section */
|
||||||
|
.input-section {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
padding: 20px;
|
||||||
|
gap: 20px;
|
||||||
|
background: #ffffff;
|
||||||
|
border-bottom: 2px solid #dee2e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-box {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: #f1f3f5;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 15px;
|
||||||
|
box-shadow: 0 2px 5px rgba(0,0,0,0.05);
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-box h2 {
|
||||||
|
margin: 0 0 10px 0;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: #343a40;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-section {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-section h3 {
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
font-size: 1rem;
|
||||||
|
color: #495057;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-row input {
|
||||||
|
flex: 1;
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid #ced4da;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-row button {
|
||||||
|
padding: 8px 12px;
|
||||||
|
background: #007bff;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-row button:hover {
|
||||||
|
background: #0056b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
background: #ffffff;
|
||||||
|
padding: 6px 10px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
border: 1px solid #dee2e6;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remove-btn {
|
||||||
|
background: #dc3545;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
padding: 4px 8px;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remove-btn:hover {
|
||||||
|
background: #b02a37;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Right side objective */
|
||||||
|
.objective {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.objective input {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid #ced4da;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.objective button {
|
||||||
|
padding: 10px;
|
||||||
|
background: #28a745;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.objective button:hover {
|
||||||
|
background: #1e7e34;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bottom output section */
|
||||||
|
.output-section {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 20px;
|
||||||
|
background: #fdfdfd;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.steps {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 15px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
border: 1px solid #dee2e6;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.steps h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
color: #495057;
|
||||||
|
}
|
||||||
|
|
||||||
|
.steps ul {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.final-result {
|
||||||
|
background: #e9f7ef;
|
||||||
|
border: 1px solid #c3e6cb;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #155724;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
256
src/app.rs
Normal file
256
src/app.rs
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
use std::iter::zip;
|
||||||
|
|
||||||
|
use yew::{Component, html};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
constraint_input::ConstraintInput, simplex::Simplex, target_input::TargetInput,
|
||||||
|
variable_input::VariableInput,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct App {
|
||||||
|
current_variable: String,
|
||||||
|
target_inputs: Vec<String>,
|
||||||
|
constraint_inputs: Vec<String>,
|
||||||
|
simplex: Simplex,
|
||||||
|
solution: Option<f32>,
|
||||||
|
final_values: Vec<(String, f32)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Msg {
|
||||||
|
VariableChange(String),
|
||||||
|
ConstraintChange((String, usize)),
|
||||||
|
TargetChange((String, usize)),
|
||||||
|
AddVariable,
|
||||||
|
ClearVariables,
|
||||||
|
AddConstraint,
|
||||||
|
ClearConstraints,
|
||||||
|
RunSimplex,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl App {}
|
||||||
|
|
||||||
|
impl Default for App {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
current_variable: Default::default(),
|
||||||
|
target_inputs: vec![],
|
||||||
|
constraint_inputs: vec!["".to_string()],
|
||||||
|
simplex: Default::default(),
|
||||||
|
solution: None,
|
||||||
|
final_values: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for App {
|
||||||
|
type Message = Msg;
|
||||||
|
|
||||||
|
type Properties = ();
|
||||||
|
|
||||||
|
fn create(_ctx: &yew::Context<Self>) -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, _ctx: &yew::Context<Self>, msg: Self::Message) -> bool {
|
||||||
|
match msg {
|
||||||
|
Msg::VariableChange(text) => self.current_variable = text,
|
||||||
|
Msg::ConstraintChange((text, i)) => {
|
||||||
|
self.constraint_inputs[i] = text;
|
||||||
|
web_sys::console::log_1(&format!("{:?}", self.constraint_inputs).into());
|
||||||
|
}
|
||||||
|
Msg::TargetChange((text, i)) => self.target_inputs[i] = text,
|
||||||
|
Msg::AddVariable => {
|
||||||
|
if self.current_variable != "".to_string()
|
||||||
|
&& !self
|
||||||
|
.simplex
|
||||||
|
.get_variables()
|
||||||
|
.contains(&self.current_variable)
|
||||||
|
{
|
||||||
|
self.simplex.add_variable(self.current_variable.clone());
|
||||||
|
self.current_variable = "".to_string();
|
||||||
|
for _ in
|
||||||
|
0..(1 + self.simplex.get_variables().len() - self.constraint_inputs.len())
|
||||||
|
{
|
||||||
|
self.constraint_inputs.push("".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
for _ in 0..(1 + self.simplex.get_variables().len() - self.target_inputs.len())
|
||||||
|
{
|
||||||
|
self.target_inputs.push("".to_string());
|
||||||
|
}
|
||||||
|
web_sys::console::log_1(&format!("{:?}", self.simplex.get_variables()).into());
|
||||||
|
web_sys::console::log_1(&format!("{:?}", self.constraint_inputs).into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Msg::ClearVariables => self.simplex.clear_variables(),
|
||||||
|
Msg::AddConstraint => {
|
||||||
|
let mut constraint = vec![0_f32; self.constraint_inputs.len()];
|
||||||
|
let mut is_ok = true;
|
||||||
|
for (i, input) in self.constraint_inputs.iter().enumerate() {
|
||||||
|
if *input == "".to_string() {
|
||||||
|
constraint[i] = 0_f32;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let Ok(v) = input.parse::<f32>() {
|
||||||
|
constraint[i] = v;
|
||||||
|
} else {
|
||||||
|
is_ok = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_ok {
|
||||||
|
self.simplex.add_constraint(constraint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Msg::ClearConstraints => self.simplex.clear_constraint(), //self.simplex.clear_constraint(),
|
||||||
|
Msg::RunSimplex => {
|
||||||
|
let mut target = vec![0_f32; self.target_inputs.len()];
|
||||||
|
let mut is_ok = true;
|
||||||
|
for (i, input) in self.target_inputs.iter().enumerate() {
|
||||||
|
if *input == "".to_string() {
|
||||||
|
target[i] = 0_f32;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let Ok(v) = input.parse::<f32>() {
|
||||||
|
target[i] = v;
|
||||||
|
} else {
|
||||||
|
is_ok = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_ok {
|
||||||
|
self.simplex.set_target(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (sol, values) = self.simplex.run_simplex();
|
||||||
|
self.solution = Some(sol);
|
||||||
|
self.final_values = values;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view(&self, ctx: &yew::Context<Self>) -> yew::Html {
|
||||||
|
let on_change_variable = ctx.link().callback(Msg::VariableChange);
|
||||||
|
let on_change_constraint = ctx.link().callback(Msg::ConstraintChange);
|
||||||
|
let on_change_target = ctx.link().callback(Msg::TargetChange);
|
||||||
|
let add_variable = ctx.link().callback(|_| Msg::AddVariable);
|
||||||
|
let clear_variables = ctx.link().callback(|_| Msg::ClearVariables);
|
||||||
|
let clear_constraint = ctx.link().callback(|_| Msg::ClearConstraints);
|
||||||
|
let add_constraint = ctx.link().callback(|_| Msg::AddConstraint);
|
||||||
|
let run_simplex = ctx.link().callback(|_| Msg::RunSimplex);
|
||||||
|
|
||||||
|
html! {
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
// <!-- Top: Input Section -->
|
||||||
|
<div class="input-section">
|
||||||
|
|
||||||
|
// <!-- Left: Variables & Constraints -->
|
||||||
|
<div class="input-box">
|
||||||
|
<h2>{"Inputs"}</h2>
|
||||||
|
|
||||||
|
// <!-- Variables -->
|
||||||
|
<div class="sub-section">
|
||||||
|
<h3>{"Variables"}</h3>
|
||||||
|
<div class="input-row">
|
||||||
|
|
||||||
|
<VariableInput {on_change_variable} value={self.current_variable.clone()} placeholder="Enter variable (e.g., x)"/>
|
||||||
|
<button onclick={add_variable}>{"Add"}</button>
|
||||||
|
<button onclick={clear_variables}>{"Clear"}</button>
|
||||||
|
</div>
|
||||||
|
<ul>
|
||||||
|
{
|
||||||
|
for self.simplex.get_variables().iter().map(|v| {
|
||||||
|
html! {
|
||||||
|
<li>{v}</li>
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
// <!-- Constraints -->
|
||||||
|
<div class="sub-section">
|
||||||
|
<h3>{"Constraints"}</h3>
|
||||||
|
<div class="input-row">
|
||||||
|
<ConstraintInput {on_change_constraint} variables={self.simplex.get_variables()}/>
|
||||||
|
<button onclick={add_constraint}>{"Add"}</button>
|
||||||
|
<button onclick={clear_constraint}>{"Clear"}</button>
|
||||||
|
</div>
|
||||||
|
<ul>
|
||||||
|
{
|
||||||
|
for self.simplex.get_constraints().iter().map(|c| {
|
||||||
|
html! {
|
||||||
|
<li>{
|
||||||
|
for zip(c, self.simplex.get_variables()).take(c.len() - 1).enumerate().map(|(i, (v, var))| {
|
||||||
|
let v_2 = if i > 0 { v.abs() } else { *v };
|
||||||
|
html! {
|
||||||
|
{ format!("{}{} {} ", if v_2 == 1_f32 { "".to_string() } else {if v_2 == -1_f32 {" -".to_string()} else { format!("{}", v_2) }}, var, {if i < c.len() - 2 {if c[i + 1] < 0_f32 {" - "} else {" + "}} else { " " }} ) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
{
|
||||||
|
format!(" ≤ {}", c[c.len() - 1])
|
||||||
|
}
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="sub-section objective">
|
||||||
|
<div>
|
||||||
|
<h3>{"Target Function"}</h3>
|
||||||
|
<TargetInput {on_change_target} variables={self.simplex.get_variables()}/>
|
||||||
|
</div>
|
||||||
|
<button onclick={run_simplex}>{"Run Simplex"}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
// <!-- Right: Objective Function -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
// <!-- Bottom: Output Section -->
|
||||||
|
<div class="output-section">
|
||||||
|
<div class="steps">
|
||||||
|
<h3>{"Steps"}</h3>
|
||||||
|
<ul>
|
||||||
|
<li>{"Step 1: Initial Tableau"}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="final-result">
|
||||||
|
<h3>{"Solution"}</h3>
|
||||||
|
// {" Final Result: Z = 50 at (x=10, y=5)"}
|
||||||
|
{
|
||||||
|
if let Some(solution) = self.solution {
|
||||||
|
html! {
|
||||||
|
<>
|
||||||
|
{format!("Z = {} at ", solution)}
|
||||||
|
{for self.final_values.iter().map(|(var, val)|{
|
||||||
|
html!{
|
||||||
|
<>
|
||||||
|
{format!("{}={} ", var, val)}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
html!{
|
||||||
|
{"Run the algorithm to find the solution"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
src/constraint_input.rs
Normal file
50
src/constraint_input.rs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
use web_sys::{HtmlInputElement, wasm_bindgen::JsCast};
|
||||||
|
use yew::{Callback, Event, Html, InputEvent, Properties, function_component, html};
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Properties)]
|
||||||
|
pub struct Props {
|
||||||
|
pub variables: Vec<String>,
|
||||||
|
pub on_change_constraint: Callback<(String, usize)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_value_from_input_event(e: InputEvent) -> String {
|
||||||
|
let event: Event = e.dyn_into().unwrap();
|
||||||
|
let event_target = event.target().unwrap();
|
||||||
|
let target: HtmlInputElement = event_target.dyn_into().unwrap();
|
||||||
|
// web_sys::console::log_1(&target.value().into());
|
||||||
|
target.value()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[function_component(ConstraintInput)]
|
||||||
|
pub fn variable_input(properties: &Props) -> Html {
|
||||||
|
let Props {
|
||||||
|
variables,
|
||||||
|
on_change_constraint,
|
||||||
|
} = properties.clone();
|
||||||
|
|
||||||
|
let oninputs: Vec<Callback<InputEvent>> = (0..variables.len() + 1)
|
||||||
|
.map(|i| {
|
||||||
|
let on_change_constraint_2 = on_change_constraint.clone();
|
||||||
|
Callback::from(move |input_event: InputEvent| {
|
||||||
|
on_change_constraint_2.emit((get_value_from_input_event(input_event), i));
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
html! {
|
||||||
|
<>
|
||||||
|
{
|
||||||
|
for variables.iter().enumerate().map(|(i, v)| {
|
||||||
|
html! {
|
||||||
|
<>
|
||||||
|
<input type="text" oninput={oninputs[i].clone()}/>
|
||||||
|
{v}{if i < variables.len() -1 {" + "} else { " " }}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
{"≤"}
|
||||||
|
<input type="text" oninput={oninputs.last().unwrap().clone()}/>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
}
|
||||||
5
src/lib.rs
Normal file
5
src/lib.rs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
pub mod app;
|
||||||
|
pub mod constraint_input;
|
||||||
|
pub mod simplex;
|
||||||
|
pub mod target_input;
|
||||||
|
pub mod variable_input;
|
||||||
15
src/main.rs
Normal file
15
src/main.rs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
use simplex_web::app::App;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// let fun = Evaluable::from_string("5 * ((2 - a) * 3)".to_string());
|
||||||
|
// println!("{:?}", fun.prefix);
|
||||||
|
|
||||||
|
// let mut val_values: HashMap<String, f32> = HashMap::new();
|
||||||
|
|
||||||
|
// val_values.insert("a".to_string(), 1.0);
|
||||||
|
// val_values.insert("b".to_string(), 2.0);
|
||||||
|
// val_values.insert("c".to_string(), 3.0);
|
||||||
|
|
||||||
|
// println!("{:?}", fun.evaluate(&val_values));
|
||||||
|
yew::Renderer::<App>::new().render();
|
||||||
|
}
|
||||||
208
src/simplex.rs
Normal file
208
src/simplex.rs
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct Simplex {
|
||||||
|
variables: Vec<String>,
|
||||||
|
constraints: Vec<Vec<f32>>,
|
||||||
|
target: Vec<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum VariableType {
|
||||||
|
Basic,
|
||||||
|
NonBasic(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Simplex {
|
||||||
|
pub fn run_simplex(&self) -> (f32, Vec<(String, f32)>) {
|
||||||
|
print_matrix(&self.constraints);
|
||||||
|
|
||||||
|
let mut matrix = vec![
|
||||||
|
vec![0_f32; self.variables.len() + self.constraints.len() + 1];
|
||||||
|
self.constraints.len() + 1
|
||||||
|
];
|
||||||
|
|
||||||
|
for (i, row) in self.constraints.iter().enumerate() {
|
||||||
|
// web_sys::console::log_1(&format!("row {} {}", i, self.constraints.len()).into());
|
||||||
|
for (j, col) in row.iter().take(self.variables.len()).enumerate() {
|
||||||
|
matrix[i][j] = *col;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i in 0..self.constraints.len() {
|
||||||
|
*matrix[i].last_mut().unwrap() = *self.constraints[i].last().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..self.constraints.len() {
|
||||||
|
matrix[i][i + self.variables.len()] = 1_f32;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i, t) in self.target.iter().take(self.target.len() - 1).enumerate() {
|
||||||
|
matrix.last_mut().unwrap()[i] = *t * -1_f32;
|
||||||
|
}
|
||||||
|
// *matrix.last_mut().unwrap().last_mut().unwrap() = *self.target.last().unwrap() * -1_f32;
|
||||||
|
// matrix.last_mut().unwrap()[0] = 1_f32;
|
||||||
|
|
||||||
|
// let mut basic_variables = self.variables.clone();
|
||||||
|
print_matrix(&matrix);
|
||||||
|
|
||||||
|
let mut solution: HashMap<String, f32> = HashMap::new();
|
||||||
|
|
||||||
|
let mut basic_variables = vec![VariableType::Basic; self.constraints.len()];
|
||||||
|
let mut non_basic_variables =
|
||||||
|
vec![VariableType::Basic; self.variables.len() + self.constraints.len() + 1];
|
||||||
|
for (i, v) in self.variables.iter().enumerate() {
|
||||||
|
non_basic_variables[i] = VariableType::NonBasic(v.clone());
|
||||||
|
solution.insert(v.clone(), 0_f32);
|
||||||
|
// web_sys::console::log_1(&format!("asdasdasd").into());
|
||||||
|
}
|
||||||
|
|
||||||
|
loop {
|
||||||
|
print_matrix(&matrix);
|
||||||
|
|
||||||
|
let pivot_column = get_pivot_column(&matrix);
|
||||||
|
let pivot_row = get_pivot_row(&matrix, pivot_column);
|
||||||
|
|
||||||
|
web_sys::console::log_1(
|
||||||
|
&format!("Pivot row: {}\nPivot col: {}\n", pivot_row, pivot_column).into(),
|
||||||
|
);
|
||||||
|
let mut exit = true;
|
||||||
|
|
||||||
|
for e in matrix.last().unwrap() {
|
||||||
|
if *e < 0_f32 {
|
||||||
|
exit = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if exit {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
web_sys::console::log_1(&format!("basic_vars {:?}", basic_variables).into());
|
||||||
|
web_sys::console::log_1(&format!("non_basic_vars {:?}", non_basic_variables).into());
|
||||||
|
|
||||||
|
let temp = basic_variables[pivot_row].clone();
|
||||||
|
basic_variables[pivot_row] = non_basic_variables[pivot_column].clone();
|
||||||
|
non_basic_variables[pivot_column] = temp;
|
||||||
|
|
||||||
|
matrix = get_new_matrix(matrix.clone(), pivot_column, pivot_row);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i, v) in basic_variables.iter().enumerate() {
|
||||||
|
if let VariableType::NonBasic(s) = v {
|
||||||
|
let sol = *matrix[i].last().unwrap();
|
||||||
|
web_sys::console::log_1(&format!("sol {}", sol).into());
|
||||||
|
solution.insert(s.clone(), sol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(
|
||||||
|
*matrix.last().unwrap().last().unwrap(),
|
||||||
|
self.variables
|
||||||
|
.iter()
|
||||||
|
.map(|v| (v.clone(), *solution.get(v).unwrap()))
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_constraint(&mut self, constraint: Vec<f32>) {
|
||||||
|
self.constraints.push(constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_constraint(&mut self) {
|
||||||
|
self.constraints.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_variable(&mut self, variable: String) {
|
||||||
|
self.variables.push(variable);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_variables(&mut self) {
|
||||||
|
self.variables.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_target(&mut self, target: Vec<f32>) {
|
||||||
|
self.target = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_constraints(&self) -> Vec<Vec<f32>> {
|
||||||
|
self.constraints.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_variables(&self) -> Vec<String> {
|
||||||
|
self.variables.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_target(&self) -> Vec<f32> {
|
||||||
|
self.target.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_matrix(m: &Vec<Vec<f32>>) {
|
||||||
|
let mut s = String::new();
|
||||||
|
|
||||||
|
for row in m {
|
||||||
|
for col in row {
|
||||||
|
s.push_str(format!("{:.2} ", col).as_str());
|
||||||
|
}
|
||||||
|
s.push_str("\n");
|
||||||
|
}
|
||||||
|
web_sys::console::log_1(&s.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_pivot_column(matrix: &Vec<Vec<f32>>) -> usize {
|
||||||
|
let mut pivot_column = 0;
|
||||||
|
|
||||||
|
for (i, e) in matrix
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.take(matrix.last().unwrap().len() - 1)
|
||||||
|
{
|
||||||
|
if *e < matrix.last().unwrap()[pivot_column] {
|
||||||
|
pivot_column = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pivot_column
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_pivot_row(matrix: &Vec<Vec<f32>>, pivot_column: usize) -> usize {
|
||||||
|
let mut pivot_row = 0;
|
||||||
|
|
||||||
|
for (i, e) in matrix.iter().enumerate().take(matrix.len() - 1) {
|
||||||
|
if e.last().unwrap() / e[pivot_column]
|
||||||
|
< matrix[pivot_row].last().unwrap() / matrix[pivot_row][pivot_column]
|
||||||
|
{
|
||||||
|
pivot_row = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pivot_row
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_new_matrix(
|
||||||
|
mut matrix: Vec<Vec<f32>>,
|
||||||
|
pivot_column: usize,
|
||||||
|
pivot_row: usize,
|
||||||
|
) -> Vec<Vec<f32>> {
|
||||||
|
let pivot_element = matrix[pivot_row][pivot_column];
|
||||||
|
|
||||||
|
for e in matrix[pivot_row].iter_mut() {
|
||||||
|
*e /= pivot_element;
|
||||||
|
}
|
||||||
|
|
||||||
|
let p_row = matrix[pivot_row].clone();
|
||||||
|
for (i, row) in matrix.iter_mut().enumerate() {
|
||||||
|
if i == pivot_row {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let pivot_c = row[pivot_column];
|
||||||
|
for (j, e) in row.iter_mut().enumerate() {
|
||||||
|
web_sys::console::log_1(&format!("e = {} - {}*{}", *e, pivot_c, p_row[j]).into());
|
||||||
|
*e -= pivot_c * p_row[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
web_sys::console::log_1(&format!("pivot_element {}", pivot_element).into());
|
||||||
|
print_matrix(&matrix);
|
||||||
|
matrix
|
||||||
|
}
|
||||||
49
src/target_input.rs
Normal file
49
src/target_input.rs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
use web_sys::{HtmlInputElement, wasm_bindgen::JsCast};
|
||||||
|
use yew::{Callback, Event, Html, InputEvent, Properties, function_component, html};
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Properties)]
|
||||||
|
pub struct Props {
|
||||||
|
pub variables: Vec<String>,
|
||||||
|
pub on_change_target: Callback<(String, usize)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_value_from_input_event(e: InputEvent) -> String {
|
||||||
|
let event: Event = e.dyn_into().unwrap();
|
||||||
|
let event_target = event.target().unwrap();
|
||||||
|
let target: HtmlInputElement = event_target.dyn_into().unwrap();
|
||||||
|
// web_sys::console::log_1(&target.value().into());
|
||||||
|
target.value()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[function_component(TargetInput)]
|
||||||
|
pub fn variable_input(properties: &Props) -> Html {
|
||||||
|
let Props {
|
||||||
|
variables,
|
||||||
|
on_change_target,
|
||||||
|
} = properties.clone();
|
||||||
|
|
||||||
|
let oninputs: Vec<Callback<InputEvent>> = (0..variables.len())
|
||||||
|
.map(|i| {
|
||||||
|
let on_change_target_2 = on_change_target.clone();
|
||||||
|
Callback::from(move |input_event: InputEvent| {
|
||||||
|
on_change_target_2.emit((get_value_from_input_event(input_event), i));
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
html! {
|
||||||
|
<>
|
||||||
|
{"Z = "}
|
||||||
|
{
|
||||||
|
for variables.iter().enumerate().map(|(i, v)| {
|
||||||
|
html! {
|
||||||
|
<>
|
||||||
|
<input type="text" oninput={oninputs[i].clone()}/>
|
||||||
|
{" "}{v}{if i < variables.len() -1 {" + "} else { "" }}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
}
|
||||||
34
src/variable_input.rs
Normal file
34
src/variable_input.rs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
use web_sys::{HtmlInputElement, wasm_bindgen::JsCast};
|
||||||
|
use yew::{Callback, Event, Html, InputEvent, Properties, function_component, html};
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Properties)]
|
||||||
|
pub struct Props {
|
||||||
|
pub value: String,
|
||||||
|
pub placeholder: String,
|
||||||
|
pub on_change_variable: Callback<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_value_from_input_event(e: InputEvent) -> String {
|
||||||
|
let event: Event = e.dyn_into().unwrap();
|
||||||
|
let event_target = event.target().unwrap();
|
||||||
|
let target: HtmlInputElement = event_target.dyn_into().unwrap();
|
||||||
|
// web_sys::console::log_1(&target.value().into());
|
||||||
|
target.value()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[function_component(VariableInput)]
|
||||||
|
pub fn variable_input(properties: &Props) -> Html {
|
||||||
|
let Props {
|
||||||
|
value,
|
||||||
|
placeholder,
|
||||||
|
on_change_variable,
|
||||||
|
} = properties.clone();
|
||||||
|
|
||||||
|
let oninput = Callback::from(move |input_event: InputEvent| {
|
||||||
|
on_change_variable.emit(get_value_from_input_event(input_event));
|
||||||
|
});
|
||||||
|
|
||||||
|
html! {
|
||||||
|
<input type="text" {value} {oninput} placeholder={placeholder}/>
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user