├── src ├── varion_frontend │ ├── src │ │ ├── vite-env.d.ts │ │ ├── assets │ │ │ └── ICLogoWhite.png │ │ ├── main.jsx │ │ ├── index.scss │ │ ├── App.jsx │ │ ├── landing │ │ │ ├── roadmap.jsx │ │ │ └── homepage.jsx │ │ └── dashboard │ │ │ ├── patients.jsx │ │ │ └── dashboard.jsx │ ├── public │ │ ├── favicon.ico │ │ ├── TechArch.png │ │ ├── gradientBg.jpg │ │ ├── varionlogo.png │ │ └── varionlogoOnly.png │ ├── index.html │ ├── tsconfig.json │ ├── package.json │ └── vite.config.js └── varion_backend │ ├── src │ ├── model.onnx │ └── lib.rs │ ├── varion_backend.did │ └── Cargo.toml ├── assets └── banner.jpg ├── Cargo.toml ├── tsconfig.json ├── .gitignore ├── dfx.json ├── package.json ├── README.md └── Cargo.lock /src/varion_frontend/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /assets/banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VarionAI/varion/HEAD/assets/banner.jpg -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "src/varion_backend" 4 | ] 5 | resolver = "2" 6 | -------------------------------------------------------------------------------- /src/varion_backend/src/model.onnx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VarionAI/varion/HEAD/src/varion_backend/src/model.onnx -------------------------------------------------------------------------------- /src/varion_frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VarionAI/varion/HEAD/src/varion_frontend/public/favicon.ico -------------------------------------------------------------------------------- /src/varion_frontend/public/TechArch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VarionAI/varion/HEAD/src/varion_frontend/public/TechArch.png -------------------------------------------------------------------------------- /src/varion_frontend/public/gradientBg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VarionAI/varion/HEAD/src/varion_frontend/public/gradientBg.jpg -------------------------------------------------------------------------------- /src/varion_frontend/public/varionlogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VarionAI/varion/HEAD/src/varion_frontend/public/varionlogo.png -------------------------------------------------------------------------------- /src/varion_frontend/public/varionlogoOnly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VarionAI/varion/HEAD/src/varion_frontend/public/varionlogoOnly.png -------------------------------------------------------------------------------- /src/varion_frontend/src/assets/ICLogoWhite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VarionAI/varion/HEAD/src/varion_frontend/src/assets/ICLogoWhite.png -------------------------------------------------------------------------------- /src/varion_backend/varion_backend.did: -------------------------------------------------------------------------------- 1 | type PredictionFailed = record { 2 | message : text; 3 | }; 4 | 5 | type PredictionResult = variant { 6 | Success : text; 7 | Failure : PredictionFailed; 8 | }; 9 | 10 | service : { 11 | prediction_result : (text) -> (PredictionResult); 12 | }; 13 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "target": "ES2020", 5 | "experimentalDecorators": true, 6 | "strictPropertyInitialization": false, 7 | "moduleResolution": "node", 8 | "allowJs": true, 9 | "outDir": "HACK_BECAUSE_OF_ALLOW_JS" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Various IDEs and Editors 2 | .vscode/ 3 | .idea/ 4 | **/*~ 5 | 6 | # Mac OSX temporary files 7 | .DS_Store 8 | **/.DS_Store 9 | 10 | # dfx temporary files 11 | .dfx/ 12 | 13 | # generated files 14 | **/declarations/ 15 | 16 | # rust 17 | target/ 18 | 19 | # frontend code 20 | node_modules/ 21 | dist/ 22 | .svelte-kit/ 23 | 24 | # environment variables 25 | .env 26 | -------------------------------------------------------------------------------- /src/varion_frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Varion AI 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /dfx.json: -------------------------------------------------------------------------------- 1 | { 2 | "canisters": { 3 | "varion_backend": { 4 | "candid": "src/varion_backend/varion_backend.did", 5 | "package": "varion_backend", 6 | "type": "rust" 7 | }, 8 | "varion_frontend": { 9 | "dependencies": [ 10 | "varion_backend" 11 | ], 12 | "source": [ 13 | "src/varion_frontend/dist" 14 | ], 15 | "type": "assets", 16 | "workspace": "varion_frontend" 17 | } 18 | }, 19 | "defaults": { 20 | "build": { 21 | "args": "", 22 | "packtool": "" 23 | } 24 | }, 25 | "output_env_file": ".env", 26 | "version": 1 27 | } -------------------------------------------------------------------------------- /src/varion_frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx", 18 | "types": ["vite/client"] 19 | }, 20 | "include": ["src"] 21 | } 22 | -------------------------------------------------------------------------------- /src/varion_backend/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "varion_backend" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [lib] 9 | crate-type = ["cdylib"] 10 | 11 | [dependencies] 12 | candid = "0.10" 13 | ic-cdk = "0.15" 14 | ic-cdk-macros = "0.15.0" 15 | ic-cdk-timers = "0.7" # Feel free to remove this dependency if you don't need timers 16 | getrandom = { version = "0.2.15", features = ["custom"] } 17 | serde = "1.0.208" 18 | prost = "0.11.0" 19 | bytes = "1.5.0" 20 | tract-onnx = { git = "https://github.com/sonos/tract", rev = "2a2914ac29390cc08963301c9f3d437b52dd321a" } -------------------------------------------------------------------------------- /src/varion_frontend/src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import App from './App'; 4 | import { InternetIdentity } from "@connect2ic/core/providers" 5 | import { createClient } from "@connect2ic/core" 6 | import { Connect2ICProvider } from "@connect2ic/react" 7 | import "@connect2ic/core/style.css" 8 | 9 | const client = createClient({ 10 | providers: [ 11 | new InternetIdentity() 12 | ], 13 | }) 14 | 15 | ReactDOM.createRoot(document.getElementById('root')).render( 16 | 17 | 18 | 19 | 20 | , 21 | ); -------------------------------------------------------------------------------- /src/varion_frontend/src/index.scss: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: sans-serif; 3 | font-size: 1.5rem; 4 | } 5 | 6 | img { 7 | max-width: 50vw; 8 | max-height: 25vw; 9 | display: block; 10 | margin: auto; 11 | } 12 | 13 | form { 14 | display: flex; 15 | justify-content: center; 16 | gap: 0.5em; 17 | flex-flow: row wrap; 18 | max-width: 40vw; 19 | margin: auto; 20 | align-items: baseline; 21 | } 22 | 23 | button[type="submit"] { 24 | padding: 5px 20px; 25 | margin: 10px auto; 26 | float: right; 27 | } 28 | 29 | #greeting { 30 | margin: 10px auto; 31 | padding: 10px 60px; 32 | border: 1px solid #222; 33 | } 34 | 35 | #greeting:empty { 36 | display: none; 37 | } 38 | -------------------------------------------------------------------------------- /src/varion_frontend/src/App.jsx: -------------------------------------------------------------------------------- 1 | import { BrowserRouter as Router, Route, Routes, Navigate } from 'react-router-dom'; 2 | import Homepage from './landing/homepage'; 3 | import Dashboard from './dashboard/dashboard'; 4 | import { useConnect } from "@connect2ic/react" 5 | 6 | console.error = () => {}; 7 | 8 | function App() { 9 | const { isConnected } = useConnect({ 10 | onConnect: () => {}, 11 | onDisconnect: () => {} 12 | }) 13 | 14 | return ( 15 | 16 | 17 | : 21 | } 22 | /> 23 | : 27 | } 28 | /> 29 | 30 | 31 | ); 32 | } 33 | 34 | export default App; -------------------------------------------------------------------------------- /src/varion_frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "varion_frontend", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "setup": "npm i && dfx canister create varion_backend && dfx generate varion_backend && dfx deploy", 8 | "start": "vite --port 3000", 9 | "prebuild": "dfx generate", 10 | "build": "tsc && vite build", 11 | "format": "prettier --write \"src/**/*.{json,js,jsx,ts,tsx,css,scss}\"" 12 | }, 13 | "dependencies": { 14 | "react": "^18.2.0", 15 | "react-dom": "^18.2.0", 16 | "@dfinity/agent": "^1.4.0", 17 | "@dfinity/candid": "^1.4.0", 18 | "@dfinity/principal": "^1.4.0" 19 | }, 20 | "devDependencies": { 21 | "@types/react": "^18.2.14", 22 | "@types/react-dom": "^18.2.6", 23 | "@vitejs/plugin-react": "^4.0.1", 24 | "dotenv": "^16.3.1", 25 | "sass": "^1.63.6", 26 | "typescript": "^5.1.3", 27 | "vite": "^4.3.9", 28 | "vite-plugin-environment": "^1.1.3" 29 | } 30 | } -------------------------------------------------------------------------------- /src/varion_frontend/vite.config.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'url'; 2 | import react from '@vitejs/plugin-react'; 3 | import { defineConfig } from 'vite'; 4 | import environment from 'vite-plugin-environment'; 5 | import dotenv from 'dotenv'; 6 | 7 | dotenv.config({ path: '../../.env' }); 8 | 9 | export default defineConfig({ 10 | build: { 11 | emptyOutDir: true, 12 | }, 13 | optimizeDeps: { 14 | esbuildOptions: { 15 | define: { 16 | global: "globalThis", 17 | }, 18 | }, 19 | }, 20 | server: { 21 | proxy: { 22 | "/api": { 23 | target: "http://127.0.0.1:4943", 24 | changeOrigin: true, 25 | }, 26 | }, 27 | }, 28 | plugins: [ 29 | react(), 30 | environment("all", { prefix: "CANISTER_" }), 31 | environment("all", { prefix: "DFX_" }), 32 | ], 33 | resolve: { 34 | alias: [ 35 | { 36 | find: "declarations", 37 | replacement: fileURLToPath( 38 | new URL("../declarations", import.meta.url) 39 | ), 40 | }, 41 | ], 42 | }, 43 | }); 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "engines": { 3 | "node": ">=16.0.0", 4 | "npm": ">=7.0.0" 5 | }, 6 | "name": "varion", 7 | "scripts": { 8 | "build": "npm run build --workspaces --if-present", 9 | "prebuild": "npm run prebuild --workspaces --if-present", 10 | "pretest": "npm run prebuild --workspaces --if-present", 11 | "start": "npm start --workspaces --if-present", 12 | "test": "npm test --workspaces --if-present" 13 | }, 14 | "type": "module", 15 | "workspaces": [ 16 | "src/varion_frontend" 17 | ], 18 | "dependencies": { 19 | "@connect2ic/core": "^0.2.0-beta.24", 20 | "@connect2ic/react": "^0.2.0-beta.24", 21 | "@emotion/react": "^11.13.3", 22 | "@emotion/styled": "^11.13.0", 23 | "@fullpage/react-fullpage": "^0.1.42", 24 | "@mui/icons-material": "^5.16.7", 25 | "@mui/material": "^5.16.7", 26 | "@nivo/bar": "^0.87.0", 27 | "framer-motion": "^11.3.30", 28 | "react": "^18.3.1", 29 | "react-dom": "^18.3.1", 30 | "react-icons": "^5.3.0", 31 | "react-intersection-observer": "^9.13.0", 32 | "react-router-dom": "^6.26.1", 33 | "styled-components": "^6.1.12" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/varion_backend/src/lib.rs: -------------------------------------------------------------------------------- 1 | use candid::{CandidType, Deserialize}; 2 | use ic_cdk::update; 3 | use prost::Message; 4 | use tract_ndarray::Array2; 5 | use tract_onnx::prelude::*; 6 | use getrandom::register_custom_getrandom; 7 | 8 | #[derive(CandidType, Deserialize)] 9 | struct PredictionFailed { 10 | message: String, 11 | } 12 | 13 | #[derive(CandidType, Deserialize)] 14 | enum PredictionResult { 15 | Success(String), 16 | Failure(PredictionFailed), 17 | } 18 | pub fn custom_getrandom(_buf: &mut [u8]) -> Result<(), getrandom::Error> { 19 | Err(getrandom::Error::UNSUPPORTED) 20 | } 21 | register_custom_getrandom!(custom_getrandom); 22 | 23 | const MODEL: &'static [u8] = include_bytes!("model.onnx"); 24 | 25 | fn parse_csv_content(csv_content: &str) -> TractResult { 26 | let mean = vec![92.56008643, 104.46793431, 96.76034648, 24.68794296, 37.15878695]; 27 | let std = vec![9.06523052, 21.02784219, 1.69851249, 9.43523536, 0.66558528]; 28 | 29 | let rows: Vec> = csv_content 30 | .lines() 31 | .map(|line| { 32 | line.split(',') 33 | .map(|s| s.parse::().unwrap()) 34 | .collect() 35 | }) 36 | .collect(); 37 | 38 | let shape = (rows.len(), rows[0].len()); 39 | let mut array = Array2::from_shape_vec(shape, rows.into_iter().flatten().collect())?; 40 | 41 | // Apply standard scaling 42 | for (_i, mut row) in array.outer_iter_mut().enumerate() { 43 | for (j, elem) in row.iter_mut().enumerate() { 44 | *elem = (*elem - mean[j]) / std[j]; 45 | } 46 | } 47 | 48 | Ok(Tensor::from(array)) 49 | } 50 | 51 | fn predict(csv_content: &str) -> TractResult { 52 | let bytes = bytes::Bytes::from_static(MODEL); 53 | let proto: tract_onnx::pb::ModelProto = tract_onnx::pb::ModelProto::decode(bytes)?; 54 | let model = tract_onnx::onnx() 55 | .model_for_proto_model(&proto)? 56 | .into_optimized()? 57 | .into_runnable()?; 58 | 59 | // Parse CSV content into a tensor 60 | let tensor = parse_csv_content(csv_content)?; 61 | 62 | // Run the model with the parsed tensor 63 | let output = model.run(tvec!(tensor.into()))?; 64 | 65 | let output_tensor = output[0].to_array_view::()?; 66 | let output_vector: Vec = output_tensor.iter().cloned().collect(); 67 | let output_string = output_vector.iter() 68 | .map(|v| v.to_string()) 69 | .collect::>() 70 | .join(","); 71 | 72 | println!("{}", output_string); 73 | Ok(output_string.to_string()) 74 | } 75 | 76 | #[update] 77 | async fn prediction_result(csv_content: String) -> PredictionResult { 78 | if csv_content.is_empty() { 79 | PredictionResult::Failure(PredictionFailed { 80 | message: "Invalid input: CSV content is empty".to_string(), 81 | }) 82 | } else { 83 | match predict(&csv_content) { 84 | Ok(predictions) => PredictionResult::Success(predictions), 85 | Err(e) => PredictionResult::Failure(PredictionFailed { 86 | message: format!("Prediction failed: {}", e), 87 | }), 88 | } 89 | } 90 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Varion AI 2 | 3 |

4 | 5 | ## Overview 6 | 7 | Varion AI is an AI research group dedicated to integrating ICP's decentralized AI into healthcare systems. Our mission is to assess the capabilities and reliability of ICP's DeAI and explore its potential to enhance the modern healthcare systems and a vision of how decentralized technologies can address these issues. 8 | 9 | Powered by the Internet Computer Protocol, Varion AI provides a secure, scalable, and decentralized infrastructure, seamlessly integrating with centralized infrastructure to bridge between Web2 and Web3 data. 10 | 11 | Deployment: https://bnm7h-gqaaa-aaaap-qht7a-cai.icp0.io/ 12 | 13 | ## Features 14 | 15 | - **Cardiovascular Disease Prediction**: Utilizes DeAI to analyze patient data and predict heart-related risks by evaluating metrics such as heart rate, blood pressure, oxygen saturation, respiratory rate, and temperature. This helps identify high-risk patients for timely interventions, reducing cardiovascular morbidity and mortality rates. 16 | - **Real-Time Monitoring Dashboard**: The user-friendly dashboard enables healthcare professionals to view and analyze patient data in real-time, allowing hospitals to update the spreadsheet with new ECG data every minute. This continuous updating ensures that the dashboard is consistently refreshed with the most recent information. 17 | - **Patient Management Strategies**: This feature allows healthcare professionals to easily search, filter, and sort patient data based on various criteria. Users can search for patients by ID, filter patients by risk level, and sort patients by cardiac probability. The feature provides real-time updates and visual indicators to help identify high-risk patients at a glance. 18 | - **On-Chain Inference**: Run machine learning models on a decentralized platform, leveraging the unique capabilities of DeAI on the Internet Computer. 19 | 20 | ## Technical Architecture 21 |

22 | 23 | ## Getting Started 24 | 25 | This section guides you through the initial setup of the necessary tools and environments for this project. We are using Rust with WebAssembly and the Dfinity platform. 26 | 27 | ### Rust Setup 28 | 29 | First, ensure you have Rust installed. We will then set the default toolchain to stable and add the WebAssembly target. 30 | 31 | 1. Install Rust and Cargo (if not already installed): Visit [Rust's installation page](https://www.rust-lang.org/tools/install). 32 | 2. Set the default toolchain to stable: 33 | ```bash 34 | rustup default stable 35 | ``` 36 | 3. Add the WebAssembly target: 37 | ```bash 38 | rustup target add wasm32-unknown-unknown 39 | ``` 40 | 41 | ### Node Package Installation 42 | Next, ensures that the project has all the necessary libraries and tools to run or build the application. 43 | ```bash 44 | npm install 45 | ``` 46 | 47 | ### Dfinity's DFX Setup 48 | 49 | We will be using Dfinity's `dfx` for our development environment. 50 | 51 | 1. Install Dfinity's `dfx`: Follow the instructions on [Dfinity's SDK documentation](https://sdk.dfinity.org/docs/quickstart/quickstart.html). 52 | 2. Starts the replica, running in the background: 53 | ```bash 54 | dfx start --background 55 | ``` 56 | 3. Deploys your canisters to the replica and generates your candid interface: 57 | ```bash 58 | dfx deploy 59 | ``` 60 | 61 | ### Start the Development Server 62 | If you are making frontend changes, you can start a development server. 63 | ```bash 64 | npm start 65 | ``` 66 | 67 | ## Varion's User Manual 68 | Once deployment is complete, check out Varion's User Manual for a comprehensive guide on how to fully utilize the application at [Varion Gitbook](https://varion.gitbook.io/varion-ai-documentation). 69 | 70 | ## Developers 71 | - Anders Willard Leo - ML Engineer 72 | - Alden Budiman - Product Manager 73 | - Brian Altan - Project Lead 74 | - Kenneth Bryan - Web3 Engineer 75 | - Terris Alvin - UI/UX Designer 76 | 77 | ## License 78 | 79 | Apache 2.0/MIT 80 | All original work licensed under either of 81 | 82 | Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) 83 | MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT) at your option. 84 | -------------------------------------------------------------------------------- /src/varion_frontend/src/landing/roadmap.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import { Box, Typography, Grow, useMediaQuery } from '@mui/material'; 3 | import { styled } from '@mui/material/styles'; 4 | import { useInView } from 'react-intersection-observer'; 5 | import { useTheme } from '@mui/material/styles'; 6 | import FiberManualRecordIcon from '@mui/icons-material/FiberManualRecord'; 7 | 8 | const RoadmapContainer = styled(Box)(({ theme }) => ({ 9 | display: 'flex', 10 | flexDirection: 'column', 11 | position: 'relative', 12 | padding: '80px 20px', 13 | width: '100%', 14 | maxWidth: '1200px', 15 | margin: '0 auto', 16 | [theme.breakpoints.up('md')]: { 17 | flexDirection: 'row', 18 | justifyContent: 'space-between', 19 | alignItems: 'stretch', 20 | }, 21 | })); 22 | 23 | const Milestone = styled(Box)(({ theme, position }) => ({ 24 | display: 'flex', 25 | flexDirection: 'column', 26 | alignItems: 'center', 27 | width: '100%', 28 | marginBottom: '40px', 29 | zIndex: 2, 30 | transition: 'transform 0.3s ease-in-out', 31 | '&:hover': { 32 | transform: 'translateY(-5px)', 33 | }, 34 | [theme.breakpoints.up('md')]: { 35 | width: '30%', 36 | position: 'absolute', 37 | left: position === 'left' ? '0%' : position === 'center' ? '35%' : '70%', 38 | marginBottom: 0, 39 | height: 'auto', 40 | display: 'flex', 41 | flexDirection: 'column', 42 | justifyContent: 'flex-start', 43 | }, 44 | })); 45 | 46 | const TextBox = styled(Box)(({ theme, maxHeight }) => ({ 47 | width: '100%', 48 | padding: '20px', 49 | backgroundColor: theme.palette.background.paper, 50 | borderRadius: '8px', 51 | boxShadow: '0 4px 6px rgba(0,0,0,0.1)', 52 | marginTop: '20px', 53 | [theme.breakpoints.up('md')]: { 54 | marginTop: '30px', 55 | height: maxHeight, 56 | }, 57 | })); 58 | 59 | const Circle = styled(Box)(({ color, theme }) => ({ 60 | width: '30px', 61 | height: '30px', 62 | borderRadius: '50%', 63 | backgroundColor: color, 64 | boxShadow: '0 4px 8px rgba(0,0,0,0.1)', 65 | transition: 'transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out', 66 | '&:hover': { 67 | transform: 'scale(1.1)', 68 | boxShadow: '0 6px 12px rgba(0,0,0,0.2)', 69 | }, 70 | [theme.breakpoints.up('md')]: { 71 | position: 'absolute', 72 | top: '-15px', 73 | }, 74 | })); 75 | 76 | const roadmapData = [ 77 | { 78 | quarter: "Q3 2024", 79 | color: '#0047AB', 80 | heading: [ 81 | 'Implementing [Internet Identity].', 82 | 'Implementing [On-chain Deep Learning Model Inference/DeAI].', 83 | 'Providing [Data Insights] and [Graphical Reports].', 84 | 'Releasing to [Mainnet] (Minimum-Viable-Product).' 85 | ], 86 | position: 'left' 87 | }, 88 | { 89 | quarter: "Q4-Q1 2025", 90 | color: '#4169E1', 91 | heading: [ 92 | '[Pre-seed] Funding.', 93 | 'Implementing [Proxy Bridge] to connect [Varion Web3] to [Web2 technologies].', 94 | 'Conducting [Open Beta] to test unreleased features on [Testnet/Playground] (Iterative Development).' 95 | ], 96 | position: 'center' 97 | }, 98 | { 99 | quarter: "Q2-Q3 2025", 100 | color: '#6495ED', 101 | heading: [ 102 | 'Implementing [Fully On-chain Training] & [Model Inference/Pure DeAI].', 103 | '[Direct Data Transmission] from Hospital\'s [ECG] data to Varion.', 104 | 'Joining on-site blockchain events to [promote Varion] & [ICP Capabilities].', 105 | 'Releasing to [Mainnet] (Market-Fit).' 106 | ], 107 | position: 'right' 108 | }, 109 | ]; 110 | 111 | const MilestoneWithAnimation = ({ milestone, index, maxHeight }) => { 112 | const [ref, inView] = useInView({ 113 | triggerOnce: true, 114 | threshold: 0.1, 115 | }); 116 | const theme = useTheme(); 117 | const isMobile = useMediaQuery(theme.breakpoints.down('md')); 118 | 119 | return ( 120 |
121 | 126 | 127 | 138 | {milestone.quarter} 139 | 140 | 141 | 142 | {milestone.heading.map((item, i) => ( 143 | 144 | 151 | 157 | {item.split('[').map((part, j) => 158 | j === 0 ? part : ( 159 | 160 | {part.split(']')[0]} 161 | {part.split(']')[1]} 162 | 163 | ) 164 | )} 165 | 166 | 167 | ))} 168 | 169 | 170 | 171 |
172 | ); 173 | }; 174 | 175 | const AnimatedTimelineLine = () => { 176 | const [ref, inView] = useInView({ 177 | triggerOnce: true, 178 | threshold: 0.1, 179 | }); 180 | const theme = useTheme(); 181 | const isMobile = useMediaQuery(theme.breakpoints.down('md')); 182 | 183 | return ( 184 |
194 | 199 | 209 | 210 |
211 | ); 212 | }; 213 | 214 | const Roadmap = () => { 215 | const theme = useTheme(); 216 | const isMobile = useMediaQuery(theme.breakpoints.down('md')); 217 | const [maxHeight, setMaxHeight] = useState('auto'); 218 | 219 | useEffect(() => { 220 | if (!isMobile) { 221 | const calculateMaxHeight = () => { 222 | let maxHeight = 0; 223 | roadmapData.forEach((milestone) => { 224 | const dummyElement = document.createElement('div'); 225 | dummyElement.style.visibility = 'hidden'; 226 | dummyElement.style.position = 'absolute'; 227 | dummyElement.style.width = '30%'; 228 | dummyElement.style.padding = '20px'; 229 | document.body.appendChild(dummyElement); 230 | 231 | const content = milestone.heading.map((item) => ` 232 |
233 | 234 | ${item} 235 |
236 | `).join(''); 237 | 238 | dummyElement.innerHTML = content; 239 | const height = dummyElement.offsetHeight; 240 | if (height > maxHeight) maxHeight = height; 241 | 242 | document.body.removeChild(dummyElement); 243 | }); 244 | 245 | return `${maxHeight-5}px`; // Add extra padding 246 | }; 247 | 248 | setMaxHeight(calculateMaxHeight()); 249 | 250 | // Recalculate on window resize 251 | const handleResize = () => { 252 | setMaxHeight(calculateMaxHeight()); 253 | }; 254 | 255 | window.addEventListener('resize', handleResize); 256 | return () => window.removeEventListener('resize', handleResize); 257 | } 258 | }, [isMobile]); 259 | 260 | return ( 261 | 262 | 263 | {roadmapData.map((milestone, index) => ( 264 | 270 | ))} 271 | 272 | ); 273 | }; 274 | 275 | export default Roadmap; -------------------------------------------------------------------------------- /src/varion_frontend/src/dashboard/patients.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import styled from "styled-components"; 3 | import { motion, AnimatePresence } from "framer-motion"; 4 | import { FiSearch, FiRefreshCw } from "react-icons/fi"; 5 | 6 | const Container = styled.section` 7 | max-width: 1100px; 8 | margin: 2rem auto; 9 | padding: 2rem; 10 | background: #fff; 11 | border-radius: 20px; 12 | box-shadow: 0 12px 30px rgba(0, 0, 0, 0.06); 13 | display: flex; 14 | flex-direction: column; 15 | gap: 1.5rem; 16 | user-select: none; 17 | `; 18 | 19 | const HeaderRow = styled.div` 20 | display: flex; 21 | flex-wrap: wrap; 22 | justify-content: space-between; 23 | align-items: center; 24 | gap: 1rem; 25 | `; 26 | 27 | const Title = styled.h2` 28 | font-size: 1.8rem; 29 | font-weight: 700; 30 | color: #1e293b; 31 | flex: 1 1 auto; 32 | `; 33 | 34 | const SearchWrapper = styled.div` 35 | position: relative; 36 | flex: 1 1 300px; 37 | max-width: 400px; 38 | display: flex; 39 | align-items: center; 40 | border: 2px solid #cbd5e1; 41 | border-radius: 50px; 42 | padding: 0.5rem 1rem; 43 | background: #f1f5f9; 44 | transition: border-color 0.3s; 45 | &:focus-within { 46 | border-color: #6366f1; 47 | } 48 | `; 49 | 50 | const SearchInput = styled.input` 51 | border: none; 52 | background: transparent; 53 | outline: none; 54 | padding-left: 0.75rem; 55 | font-size: 1rem; 56 | width: 100%; 57 | color: #334155; 58 | font-weight: 500; 59 | 60 | &::placeholder { 61 | color: #94a3b8; 62 | } 63 | `; 64 | 65 | const IconSearch = styled(FiSearch)` 66 | flex-shrink: 0; 67 | color: #64748b; 68 | font-size: 1.25rem; 69 | `; 70 | 71 | const ButtonRefresh = styled.button` 72 | background: #6366f1; 73 | color: white; 74 | border: none; 75 | padding: 0.55rem 1.25rem; 76 | font-weight: 600; 77 | border-radius: 40px; 78 | display: flex; 79 | align-items: center; 80 | gap: 0.5rem; 81 | cursor: pointer; 82 | transition: background-color 0.25s; 83 | 84 | &:hover { 85 | background-color: #4f46e5; 86 | } 87 | 88 | &:focus-visible { 89 | outline: 3px solid #4f46e5; 90 | outline-offset: 2px; 91 | } 92 | `; 93 | 94 | const FiltersContainer = styled.div` 95 | display: flex; 96 | flex-wrap: wrap; 97 | gap: 12px; 98 | justify-content: center; 99 | user-select: none; 100 | `; 101 | 102 | const FilterButton = styled.button` 103 | padding: 0.5rem 1.3rem; 104 | font-weight: 600; 105 | font-size: 0.9rem; 106 | border-radius: 9999px; 107 | border: 2px solid transparent; 108 | cursor: pointer; 109 | background: ${({ active }) => (active ? "#4f46e5" : "#e0e7ff")}; 110 | color: ${({ active }) => (active ? "#f3f4f6" : "#4f46e5")}; 111 | transition: background-color 0.3s, color 0.3s; 112 | 113 | &:hover:not(:disabled) { 114 | background-color: ${({ active }) => 115 | active ? "#4338ca" : "#c7d2fe"}; 116 | } 117 | `; 118 | 119 | const SortContainer = styled.div` 120 | display: flex; 121 | justify-content: center; 122 | align-items: center; 123 | gap: 12px; 124 | margin-top: 0.5rem; 125 | user-select: none; 126 | `; 127 | 128 | const SortCheckbox = styled.input` 129 | cursor: pointer; 130 | width: 18px; 131 | height: 18px; 132 | `; 133 | 134 | const SortLabel = styled.label` 135 | font-weight: 600; 136 | color: #4f46e5; 137 | cursor: pointer; 138 | user-select: none; 139 | `; 140 | 141 | const LastUpdate = styled.p` 142 | text-align: center; 143 | font-size: 0.9rem; 144 | color: #64748b; 145 | margin-top: 0.5rem; 146 | font-style: italic; 147 | user-select: none; 148 | `; 149 | 150 | const TableWrapper = styled.div` 151 | overflow-x: auto; 152 | border-radius: 14px; 153 | box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.05); 154 | `; 155 | 156 | const TableGrid = styled.div` 157 | display: grid; 158 | grid-template-columns: repeat(7, minmax(120px, 1fr)); 159 | gap: 10px; 160 | min-width: 700px; 161 | 162 | @media (max-width: 640px) { 163 | grid-template-columns: repeat(4, minmax(100px, 1fr)); 164 | min-width: 400px; 165 | } 166 | `; 167 | 168 | const TableHeader = styled.div` 169 | font-weight: 700; 170 | color: #64748b; 171 | background-color: #f8fafc; 172 | padding: 14px 12px; 173 | border-radius: 10px; 174 | text-align: center; 175 | user-select: none; 176 | 177 | @media (max-width: 640px) { 178 | padding: 10px 8px; 179 | } 180 | `; 181 | 182 | const TableCell = styled(motion.div)` 183 | background-color: ${({ riskColor }) => riskColor ? riskColor : "#f8fafc"}; 184 | padding: 12px 10px; 185 | border-radius: 10px; 186 | text-align: center; 187 | font-weight: 500; 188 | color: #1e293b; 189 | transition: background-color 0.3s ease; 190 | 191 | &:hover { 192 | background-color: #e0e7ff; 193 | } 194 | 195 | @media (max-width: 640px) { 196 | font-size: 0.85rem; 197 | padding: 10px 6px; 198 | } 199 | `; 200 | 201 | const getRiskColor = (riskLevel) => { 202 | switch (riskLevel) { 203 | case "High Risk": 204 | return "rgba(244, 67, 54, 0.15)"; 205 | case "Medium Risk": 206 | return "rgba(255, 235, 59, 0.15)"; 207 | case "Low Risk": 208 | return "rgba(76, 175, 80, 0.15)"; 209 | default: 210 | return "#f8fafc"; 211 | } 212 | }; 213 | 214 | const Patients = ({ patientData, onRefresh }) => { 215 | const [patients, setPatients] = useState([]); 216 | const [searchTerm, setSearchTerm] = useState(""); 217 | const [riskFilter, setRiskFilter] = useState("All"); 218 | const [sortByRiskLevel, setSortByRiskLevel] = useState(false); 219 | const [lastUpdateTime, setLastUpdateTime] = useState("Not available"); 220 | 221 | useEffect(() => { 222 | setPatients(patientData); 223 | if (patientData.length > 0 && patientData[0].lastUpdated) { 224 | setLastUpdateTime(patientData[0].lastUpdated); 225 | } 226 | }, [patientData]); 227 | 228 | const filteredAndSortedPatients = patients 229 | .filter( 230 | (p) => 231 | p.id.toLowerCase().includes(searchTerm.toLowerCase()) && 232 | (riskFilter === "All" || p.riskLevel === riskFilter) 233 | ) 234 | .sort((a, b) => { 235 | if (sortByRiskLevel) { 236 | return b.cardiacProba - a.cardiacProba; 237 | } 238 | return 0; 239 | }); 240 | 241 | return ( 242 | 243 | 244 | Patient Data 245 | 246 | 256 | onRefresh && onRefresh()} 259 | > 260 | 261 | Refresh 262 | 263 | 264 | 265 | 266 | {["All", "Low Risk", "Medium Risk", "High Risk"].map((level) => ( 267 | setRiskFilter(level)} 271 | aria-pressed={riskFilter === level} 272 | > 273 | {level} 274 | 275 | ))} 276 | 277 | 278 | 279 | setSortByRiskLevel(e.target.checked)} 284 | /> 285 | 286 | Sort by highest Cardiac Probability 287 | 288 | 289 | 290 | Last Updated: {lastUpdateTime} 291 | 292 | 293 | 294 | Patient ID 295 | HR 296 | BP 297 | SpO₂ 298 | Resp 299 | Temp (°C) 300 | Risk Level 301 | 302 | 303 | {filteredAndSortedPatients.map((patient) => ( 304 | 305 | 314 | {patient.id} 315 | 316 | 317 | {patient.HR} 318 | 319 | 320 | {patient.BP} 321 | 322 | 323 | {patient.SpO2} 324 | 325 | 326 | {patient.RESP} 327 | 328 | 329 | {patient.TEMP} 330 | 331 | 332 | {patient.riskLevel} 333 | 334 | 335 | ))} 336 | 337 | 338 | 339 | 340 | ); 341 | }; 342 | 343 | export default Patients; 344 | -------------------------------------------------------------------------------- /src/varion_frontend/src/landing/homepage.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import ReactFullpage from '@fullpage/react-fullpage'; 3 | import { motion, AnimatePresence } from 'framer-motion'; 4 | import styled from 'styled-components'; 5 | import { useInView } from 'react-intersection-observer'; 6 | import { ConnectButton, ConnectDialog } from '@connect2ic/react'; 7 | import ArrowForwardIcon from '@mui/icons-material/KeyboardArrowRight'; 8 | import ICLogo from '../assets/ICLogoWhite.png'; 9 | import Roadmap from './roadmap'; 10 | 11 | const featuresData = [ 12 | { 13 | title: 'AI-Powered Insights', 14 | description: 15 | 'Harness AI for real-time predictive analytics on patient health and hospital operations, transforming healthcare delivery.', 16 | icon: '🧠', 17 | }, 18 | { 19 | title: 'Seamless Integration', 20 | description: 21 | 'Smoothly embed Varion’s decentralized solutions within existing hospital IT infrastructure without disruption.', 22 | icon: '🔗', 23 | }, 24 | { 25 | title: 'Enhanced Security', 26 | description: 27 | 'Leverage Internet Identity for decentralized secure identities — no passwords required, full privacy guaranteed.', 28 | icon: '🔐', 29 | }, 30 | { 31 | title: 'On-Chain Inference', 32 | description: 33 | 'Deploy deep learning directly on-chain via Internet Computer for transparent, verifiable healthcare AI insights.', 34 | icon: '🔄', 35 | }, 36 | { 37 | title: 'Scalable Architecture', 38 | description: 39 | 'Designed to scale effortlessly, Varion accommodates growing hospitals and healthcare networks anywhere globally.', 40 | icon: '📈', 41 | }, 42 | { 43 | title: 'AI Model Marketplace', 44 | description: 45 | 'A decentralized store for hospitals and developers to share, license, and collaborate on specialized AI models.', 46 | icon: '🛒', 47 | }, 48 | ]; 49 | 50 | const FeatureCard = ({ feature, index }) => { 51 | const [ref, inView] = useInView({ threshold: 0.25, triggerOnce: true }); 52 | 53 | return ( 54 | 67 | {feature.icon} 68 |

{feature.title}

69 |

{feature.description}

70 |
71 | ); 72 | }; 73 | 74 | const PrivacyPolicyPopup = ({ isOpen, onClose }) => ( 75 | 76 | {isOpen && ( 77 | 83 | e.stopPropagation()} 88 | > 89 | × 90 |

Privacy Policy

91 |

92 | Our platform is designed with your privacy in mind, ensuring that no personal data is stored on our servers. We do not collect, retain, or share any user data. When you interact with our website, all information you provide is used solely for the duration of your session. 93 |

94 |
95 |
96 | )} 97 |
98 | ); 99 | 100 | const Homepage = () => { 101 | const [isPrivacyPolicyOpen, setIsPrivacyPolicyOpen] = useState(false); 102 | 103 | return ( 104 | 105 | 111 | 112 | 117 | 118 | 119 | 124 | 125 | 126 | 127 | Launch Varion 128 | 129 | 130 | 131 | 132 | 133 | 134 | ( 143 | 144 |
145 | 146 | 147 | 152 | Revolutionizing Healthcare with Decentralized AI 153 | 154 | 159 | Introducing a Decentralized AI Monitoring Dashboard
160 | Elevate patient care and safety to unprecedented levels. 161 |
162 | 163 | 170 | 171 |
172 |
173 |
174 |
175 | 176 | 181 | Why Varion? 182 | 183 | 184 | {featuresData.map((feature, index) => ( 185 | 186 | ))} 187 | 188 | 189 |
190 |
191 | 192 | 197 | Our Roadmap 198 | 199 | 200 | 201 |
202 |
203 |
204 | 209 | © 2024 Varion. All rights reserved. 210 | 211 | 212 | setIsPrivacyPolicyOpen(true)} 218 | > 219 | Privacy Policy 220 | 221 | 222 |
223 |
224 |
225 | )} 226 | /> 227 | setIsPrivacyPolicyOpen(false)} 230 | /> 231 |
232 |
233 | ); 234 | }; 235 | 236 | /* --- STYLED COMPONENTS --- */ 237 | 238 | const Container = styled(motion.div)` 239 | font-family: 'Inter', 'Poppins', 'Helvetica Neue', Arial, sans-serif; 240 | background: linear-gradient(135deg, #e3f2fd 0%, #ffffff 100%); 241 | color: #121926; 242 | min-height: 100vh; 243 | display: flex; 244 | flex-direction: column; 245 | letter-spacing: 0.015em; 246 | font-size: 1rem; 247 | font-weight: 400; 248 | `; 249 | 250 | const Navbar = styled.nav` 251 | position: fixed; 252 | top: 0; 253 | left: 0; right: 0; 254 | height: 64px; 255 | padding: 0 2.5rem; 256 | display: flex; 257 | justify-content: space-between; 258 | align-items: center; 259 | backdrop-filter: saturate(180%) blur(12px); 260 | background: rgba(255 255 255 / 0.25); 261 | border-bottom: 1.3px solid rgba(255 255 255 / 0.4); 262 | box-shadow: 0 6px 32px rgba(20, 40, 90, 0.15); 263 | z-index: 1100; 264 | 265 | @media (max-width: 600px) { 266 | padding: 0 1.15rem; 267 | height: 54px; 268 | } 269 | `; 270 | 271 | const Logo = styled.img` 272 | height: 2.3rem; 273 | width: auto; 274 | cursor: pointer; 275 | `; 276 | 277 | const StyledConnectButton = styled.div` 278 | .connect-button { 279 | background: linear-gradient(90deg, #1a75ed 0%, #36aade 100%); 280 | color: #fff; 281 | border: none; 282 | padding: 0.55rem 1.55rem; 283 | border-radius: 23px; 284 | cursor: pointer; 285 | font-weight: 600; 286 | text-transform: uppercase; 287 | letter-spacing: 0.55px; 288 | transition: box-shadow 0.22s ease, background 0.3s ease; 289 | box-shadow: 0 3px 18px rgba(66, 133, 244, 0.35); 290 | display: flex; 291 | align-items: center; 292 | font-size: 1.05rem; 293 | 294 | &:hover { 295 | background: linear-gradient(90deg, #0e53a4 0%, #208bd9 100%); 296 | box-shadow: 0 6px 28px rgba(66, 133, 244, 0.5); 297 | } 298 | span { 299 | margin-right: 6px; 300 | letter-spacing: 0.6px; 301 | } 302 | svg { 303 | font-size: 1.3rem; 304 | margin-left: 8px; 305 | } 306 | } 307 | `; 308 | 309 | const Hero = styled.section` 310 | min-height: 100vh; 311 | display: flex; 312 | justify-content: center; 313 | align-items: center; 314 | padding: 0 1rem; 315 | background: linear-gradient(135deg, #eef5fb 0%, #cde6fc 100%); 316 | `; 317 | 318 | const HeroContentGlass = styled(motion.div)` 319 | background: rgba(255 255 255 / 0.3); 320 | box-shadow: 0 8px 36px rgba(0, 123, 255, 0.18); 321 | backdrop-filter: saturate(180%) blur(15px); 322 | border-radius: 28px; 323 | padding: 3.5rem 3rem; 324 | max-width: 38rem; 325 | color: #101828; 326 | text-align: center; 327 | 328 | h1 { 329 | font-size: 2.7rem; 330 | font-weight: 700; 331 | color: #003a8c; 332 | margin-bottom: 1.15rem; 333 | letter-spacing: 0.01em; 334 | user-select: none; 335 | } 336 | 337 | p { 338 | font-size: 1.21rem; 339 | margin-bottom: 2rem; 340 | font-weight: 500; 341 | color: #2455b2d9; 342 | user-select: none; 343 | } 344 | 345 | @media (max-width: 420px) { 346 | padding: 3rem 2rem; 347 | h1 { 348 | font-size: 2.1rem; 349 | } 350 | } 351 | `; 352 | 353 | const LogoContainer = styled.div` 354 | margin-top: 2rem; 355 | display: flex; 356 | justify-content: center; 357 | img { 358 | height: 1.6rem; 359 | width: auto; 360 | filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.1)); 361 | } 362 | `; 363 | 364 | const About = styled.section` 365 | padding: 3rem 1rem 3rem; 366 | background: linear-gradient(135deg, #c8e1ff 0%, #f5fbff 100%); 367 | min-height: auto; 368 | display: flex; 369 | flex-direction: column; 370 | 371 | h2 { 372 | font-size: 1.7rem; 373 | font-weight: 700; 374 | margin-bottom: 2.8rem; 375 | color: #204192e8; 376 | text-align: center; 377 | letter-spacing: 0.02em; 378 | user-select: none; 379 | } 380 | `; 381 | 382 | const Features = styled.div` 383 | display: grid; 384 | grid-template-columns: repeat(auto-fit,minmax(300px,1fr)); 385 | gap: 1.8rem; 386 | max-width: 1200px; 387 | margin: 0 auto; 388 | `; 389 | 390 | const FeatureGlass = styled(motion.div)` 391 | background: rgba(255 255 255 / 0.28); 392 | border-radius: 20px; 393 | padding: 1.5rem 1.7rem; 394 | box-shadow: 0 14px 40px rgba(3, 67, 251, 0.1); 395 | backdrop-filter: saturate(190%) blur(22px); 396 | border: 1.2px solid rgba(255 255 255 / 0.35); 397 | cursor: default; 398 | display: flex; 399 | flex-direction: column; 400 | transition: all 0.3s ease; 401 | min-height: 220px; 402 | 403 | h3 { 404 | color: #064091; 405 | font-weight: 700; 406 | margin: 0.4rem 0 1rem 0; 407 | font-size: 1.12rem; 408 | letter-spacing: 0.01em; 409 | } 410 | p { 411 | color: #3755a4dd; 412 | font-weight: 500; 413 | margin: 0; 414 | font-size: 0.97rem; 415 | flex-grow: 1; 416 | } 417 | `; 418 | 419 | const FeatureIcon = styled.div` 420 | font-size: 2.3rem; 421 | color: #1862f0; 422 | user-select: none; 423 | transition: transform 0.18s ease-out; 424 | 425 | ${FeatureGlass}:hover & { 426 | transform: scale(1.25) rotate(7deg); 427 | } 428 | `; 429 | 430 | const RoadmapSection = styled.section` 431 | padding: 3rem 1.4rem 4rem; 432 | min-height: 100vh; 433 | background: linear-gradient(150deg, #dbe8ff 0%, #f8fbff 100%); 434 | display: flex; 435 | flex-direction: column; 436 | justify-content: center; 437 | 438 | h2 { 439 | font-weight: 700; 440 | font-size: 1.65rem; 441 | margin-bottom: 2.3rem; 442 | color: #004bb5cc; 443 | text-align: center; 444 | letter-spacing: 0.01em; 445 | user-select: none; 446 | } 447 | `; 448 | 449 | const Footer = styled.footer` 450 | background: rgba(255 255 255 / 0.6); 451 | backdrop-filter: saturate(180%) blur(20px); 452 | padding: 3rem 1.5rem; 453 | border-top: 1.6px solid rgba(0, 0, 0, 0.05); 454 | text-align: center; 455 | color: #3d4668dd; 456 | font-size: 0.92rem; 457 | user-select: none; 458 | `; 459 | 460 | const FooterLinks = styled.div` 461 | margin-top: 1.7rem; 462 | 463 | a { 464 | color: #2060f0dd; 465 | text-decoration: none; 466 | font-weight: 600; 467 | margin: 0 1.3rem; 468 | transition: color 0.3s ease, transform 0.3s ease; 469 | 470 | &:hover, 471 | &:focus { 472 | color: #134ac0; 473 | transform: translateY(-3px); 474 | text-decoration: underline; 475 | } 476 | } 477 | `; 478 | 479 | const PopupOverlay = styled(motion.div)` 480 | position: fixed; 481 | inset: 0; 482 | background-color: rgba(14, 17, 22, 0.71); 483 | display: flex; 484 | justify-content: center; 485 | align-items: center; 486 | z-index: 1300; 487 | `; 488 | 489 | const PopupContent = styled(motion.div)` 490 | background: rgba(255 255 255 / 0.9); 491 | width: 90%; 492 | max-width: 480px; 493 | border-radius: 22px; 494 | padding: 2rem 2.4rem; 495 | box-shadow: 0 14px 50px rgb(33 111 242 / 0.3); 496 | backdrop-filter: saturate(150%) blur(24px); 497 | position: relative; 498 | 499 | h2 { 500 | color: #1044a4; 501 | margin-bottom: 1.2rem; 502 | font-weight: 700; 503 | font-size: 1.5rem; 504 | user-select: none; 505 | } 506 | 507 | p { 508 | color: #2d2f33dd; 509 | line-height: 1.65; 510 | font-weight: 500; 511 | } 512 | `; 513 | 514 | const PopupCloseButton = styled.button` 515 | position: absolute; 516 | top: 14px; 517 | right: 14px; 518 | background: transparent; 519 | border: none; 520 | font-size: 2rem; 521 | line-height: 1; 522 | cursor: pointer; 523 | color: #0c52a4; 524 | font-weight: 700; 525 | transition: color 0.2s ease; 526 | 527 | &:hover, 528 | &:focus { 529 | color: #093779; 530 | } 531 | `; 532 | 533 | const HideFullpageCredits = styled.div` 534 | .fp-watermark { 535 | display: none !important; 536 | } 537 | `; 538 | 539 | export default () => ( 540 | 541 | 542 | 543 | ); 544 | -------------------------------------------------------------------------------- /src/varion_frontend/src/dashboard/dashboard.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, useRef } from "react"; 2 | import styled from "styled-components"; 3 | import { motion, AnimatePresence } from "framer-motion"; 4 | import Patients from "./patients"; 5 | import { FiHome, FiHeart, FiLogOut } from "react-icons/fi"; 6 | import { FiAlertCircle } from "react-icons/fi"; 7 | import { useConnect } from "@connect2ic/react"; 8 | import { varion_backend } from "declarations/varion_backend"; 9 | import { ResponsiveBar } from "@nivo/bar"; 10 | 11 | /* --- STYLE VARIABLES FOR VARION THEME --- */ 12 | const colors = { 13 | primaryGradient: "linear-gradient(90deg, #1a75ed 0%, #36aade 100%)", 14 | primaryGradientHover: "linear-gradient(90deg, #0e53a4 0%, #208bd9 100%)", 15 | primaryText: "#064091", 16 | secondaryText: "#3755a4dd", 17 | backgroundLight: "rgba(255 255 255 / 0.28)", 18 | backgroundGlass: "rgba(255 255 255 / 0.3)", 19 | backgroundLightSolid: "#edf2f7", 20 | shadowBlue: "rgba(0, 123, 255, 0.18)", 21 | shadowSubtle: "rgba(0, 0, 0, 0.05)", 22 | sidebarGradient: 23 | "linear-gradient(359.3deg, rgb(196, 214, 252) 1%, rgba(187, 187, 187, 0) 70.9%)", 24 | modalOverlay: "rgba(14, 17, 22, 0.71)", 25 | modalBackground: "rgba(255 255 255 / 0.9)", 26 | errorRed: "#ef4444", 27 | errorHoverRed: "#dc2626", 28 | white: "#fff", 29 | grayText: "#3d4668dd", 30 | lightGrayText: "#7a8793", 31 | linkBlue: "#2060f0dd", 32 | linkBlueHover: "#134ac0", 33 | }; 34 | 35 | const DashboardContainer = styled.div` 36 | display: flex; 37 | height: 100vh; 38 | background: linear-gradient(135deg, #e3f2fd 0%, #ffffff 100%); 39 | font-family: "Inter", "Poppins", "Helvetica Neue", Arial, sans-serif; 40 | color: ${colors.primaryText}; 41 | letter-spacing: 0.015em; 42 | `; 43 | 44 | /* SIDEBAR STYLES */ 45 | const Sidebar = styled(motion.aside)` 46 | background: ${colors.sidebarGradient}; 47 | min-width: 80px; 48 | height: 100%; 49 | display: flex; 50 | flex-direction: column; 51 | overflow: hidden; 52 | box-shadow: 0 6px 32px rgba(20, 40, 90, 0.15); 53 | border-right: 1.3px solid rgba(255 255 255 / 0.4); 54 | user-select: none; 55 | z-index: 1200; 56 | `; 57 | 58 | const Logo = styled(motion.div)` 59 | padding: 30px 20px; 60 | text-align: center; 61 | margin-bottom: 30px; 62 | overflow: hidden; 63 | img { 64 | height: auto; 65 | } 66 | `; 67 | 68 | const Nav = styled.nav` 69 | ul { 70 | list-style: none; 71 | padding: 0; 72 | margin: 0; 73 | } 74 | `; 75 | 76 | const NavItem = styled(motion.li)` 77 | padding: 18px 25px; 78 | cursor: pointer; 79 | display: flex; 80 | align-items: center; 81 | color: #677294; 82 | font-size: 1.15rem; 83 | font-weight: 600; 84 | border-radius: 12px; 85 | margin: 8px 15px; 86 | user-select: none; 87 | transition: all 0.25s ease; 88 | 89 | &:hover, 90 | &:focus-visible { 91 | background: rgba(3, 67, 251, 0.11); 92 | color: ${colors.primaryText}; 93 | box-shadow: 0 10px 40px rgba(3, 67, 251, 0.15); 94 | outline-offset: 3px; 95 | } 96 | 97 | &.active { 98 | background: ${colors.backgroundGlass}; 99 | box-shadow: 0 14px 40px rgba(3, 67, 251, 0.18); 100 | color: ${colors.primaryText}; 101 | } 102 | `; 103 | 104 | const Icon = styled.span` 105 | font-size: 1.75rem; 106 | min-width: 30px; 107 | display: flex; 108 | justify-content: center; 109 | color: inherit; 110 | `; 111 | 112 | const Label = styled(motion.span)` 113 | margin-left: 15px; 114 | white-space: nowrap; 115 | color: inherit; 116 | user-select: none; 117 | `; 118 | 119 | /* MAIN CONTENT */ 120 | const MainContent = styled.main` 121 | flex-grow: 1; 122 | padding: 2.25rem 3rem; 123 | overflow-y: auto; 124 | background: ${colors.white}; 125 | border-radius: 28px; 126 | margin: 20px 40px 20px 20px; 127 | box-shadow: 0 8px 36px rgba(0, 123, 255, 0.18); 128 | display: flex; 129 | flex-direction: column; 130 | min-width: 0; 131 | `; 132 | 133 | /* DASHBOARD BOX */ 134 | const DashboardContent = styled.section` 135 | padding: 2rem 2.5rem; 136 | background: ${colors.backgroundGlass}; 137 | border-radius: 28px; 138 | box-shadow: 0 14px 50px rgb(33 111 242 / 0.3); 139 | color: ${colors.primaryText}; 140 | flex-grow: 1; 141 | display: flex; 142 | flex-direction: column; 143 | `; 144 | 145 | /* CHART WRAPPER */ 146 | const ChartContainer = styled.div` 147 | height: 400px; 148 | margin-bottom: 2rem; 149 | background: ${colors.backgroundLightSolid}; 150 | border-radius: 15px; 151 | padding: 24px; 152 | box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.07); 153 | `; 154 | 155 | /* CHART HEADER */ 156 | const ChartHeader = styled.div` 157 | display: flex; 158 | justify-content: space-between; 159 | align-items: center; 160 | margin-bottom: 1.75rem; 161 | user-select: none; 162 | `; 163 | 164 | const ChartTitle = styled.h2` 165 | font-size: 2rem; 166 | font-weight: 700; 167 | margin: 0; 168 | color: ${colors.primaryText}; 169 | `; 170 | 171 | /* FORM & INPUTS */ 172 | const InputContainer = styled.div` 173 | display: flex; 174 | flex-direction: column; 175 | gap: 1.5rem; 176 | background: ${colors.backgroundLightSolid}; 177 | padding: 2rem 2.5rem; 178 | border-radius: 22px; 179 | box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.06); 180 | user-select: none; 181 | `; 182 | 183 | const InstructionText = styled.p` 184 | font-weight: 600; 185 | font-size: 1.125rem; 186 | margin: 0; 187 | user-select: text; 188 | color: ${colors.primaryText}; 189 | `; 190 | 191 | const StyledInput = styled.input` 192 | padding: 14px 20px; 193 | border: 1.5px solid #d1d9e6; 194 | border-radius: 16px; 195 | font-size: 1rem; 196 | width: 100%; 197 | color: ${colors.primaryText}; 198 | letter-spacing: 0.015em; 199 | transition: border-color 0.3s ease; 200 | 201 | &:focus { 202 | outline: none; 203 | border-color: ${colors.primaryGradientHover}; 204 | box-shadow: 0 0 10px ${colors.primaryGradientHover}; 205 | } 206 | `; 207 | 208 | const StyledButton = styled.button` 209 | background: ${colors.primaryGradient}; 210 | color: ${colors.white}; 211 | border: none; 212 | padding: 14px 28px; 213 | border-radius: 24px; 214 | font-weight: 700; 215 | font-size: 1.05rem; 216 | cursor: pointer; 217 | width: 100%; 218 | letter-spacing: 0.6px; 219 | box-shadow: 0 8px 30px rgba(66, 133, 244, 0.35); 220 | transition: background 0.3s ease, box-shadow 0.22s ease; 221 | 222 | &:hover:not(:disabled) { 223 | background: ${colors.primaryGradientHover}; 224 | box-shadow: 0 12px 48px rgba(66, 133, 244, 0.5); 225 | } 226 | 227 | &:disabled { 228 | background-color: #a0aec0; 229 | cursor: not-allowed; 230 | box-shadow: none; 231 | } 232 | `; 233 | 234 | const StyledStartButton = styled(StyledButton)` 235 | background-color: #f54b9e; 236 | 237 | &:hover:not(:disabled) { 238 | background-color: #f7288d; 239 | } 240 | `; 241 | 242 | const ConfirmButton = styled(StyledButton)` 243 | width: 85%; 244 | `; 245 | 246 | const CancelButton = styled(StyledButton)` 247 | background-color: #ef4444; 248 | margin-left: 12px; 249 | width: 15%; 250 | 251 | &:hover:not(:disabled) { 252 | background-color: ${colors.errorHoverRed}; 253 | } 254 | `; 255 | 256 | /* EXAMPLE TABLE */ 257 | const ExampleTable = styled.table` 258 | border-collapse: separate; 259 | border-spacing: 0; 260 | width: 100%; 261 | margin-top: 0.75rem; 262 | border-radius: 12px; 263 | overflow: hidden; 264 | box-shadow: 0 0 24px rgb(33 111 242 / 0.12); 265 | user-select: none; 266 | `; 267 | 268 | const TableHeader = styled.th` 269 | background: ${colors.backgroundLightSolid}; 270 | font-weight: 600; 271 | font-size: 1rem; 272 | color: ${colors.primaryText}; 273 | padding: 12px 16px; 274 | text-align: center; 275 | width: ${(props) => (props.narrow ? "4%" : "16%")}; 276 | border-bottom: 1.5px solid #cbd5e0; 277 | 278 | user-select: none; 279 | `; 280 | 281 | const TableCell = styled.td` 282 | padding: 12px 16px; 283 | text-align: center; 284 | font-size: 0.95rem; 285 | color: ${colors.secondaryText}; 286 | width: ${(props) => (props.narrow ? "4%" : "16%")}; 287 | border-bottom: 1.5px solid #cbd5e0; 288 | user-select: none; 289 | 290 | ${(props) => 291 | props.bordered && 292 | ` 293 | border-left: 1.5px solid #cbd5e0; 294 | border-right: 1.5px solid #cbd5e0; 295 | `} 296 | `; 297 | 298 | const TableNotes = styled.p` 299 | margin-top: 1.25rem; 300 | color: ${colors.lightGrayText}; 301 | font-weight: 700; 302 | font-size: 1rem; 303 | text-align: center; 304 | user-select: none; 305 | `; 306 | 307 | /* MODAL */ 308 | const Modal = styled(motion.div)` 309 | position: fixed; 310 | inset: 0; 311 | background-color: ${colors.modalOverlay}; 312 | display: flex; 313 | justify-content: center; 314 | align-items: center; 315 | z-index: 1400; 316 | `; 317 | 318 | const ModalContent = styled(motion.div)` 319 | background: ${colors.modalBackground}; 320 | padding: 2.5rem 3rem; 321 | border-radius: 28px; 322 | box-shadow: 0 14px 50px rgb(33 111 242 / 0.3); 323 | max-width: 440px; 324 | width: 90%; 325 | text-align: center; 326 | user-select: none; 327 | 328 | p { 329 | margin: 1.25rem 0 0 0; 330 | font-weight: 700; 331 | font-size: 1.25rem; 332 | color: ${colors.primaryText}; 333 | } 334 | `; 335 | 336 | const ErrorIcon = styled(FiAlertCircle)` 337 | font-size: 60px; 338 | color: ${colors.errorRed}; 339 | `; 340 | 341 | const ModalButton = styled(StyledButton)` 342 | max-width: 250px; 343 | margin-top: 1.75rem; 344 | `; 345 | 346 | /* NO DATA MESSAGE */ 347 | const NoDataMessage = styled.div` 348 | height: 100%; 349 | color: #718096; 350 | font-weight: 600; 351 | font-size: 1.15rem; 352 | display: flex; 353 | justify-content: center; 354 | align-items: center; 355 | user-select: none; 356 | `; 357 | 358 | /* UTILS */ 359 | const maskToken = (token) => { 360 | if (!token || token.length <= 10) return ""; 361 | const end = token.slice(-4); 362 | return `********${end}`; 363 | }; 364 | 365 | const Dashboard = () => { 366 | const [isExpanded, setIsExpanded] = useState(false); 367 | const [activeComponent, setActiveComponent] = useState("dashboard"); 368 | const [isSigningOut, setIsSigningOut] = useState(false); 369 | const { disconnect } = useConnect(); 370 | const [chartData, setChartData] = useState([]); 371 | const [link, setLink] = useState(""); 372 | const [token, setToken] = useState(""); 373 | const [modalError, setModalError] = useState(null); 374 | const [isEditing, setIsEditing] = useState(false); 375 | const [isSubmitted, setIsSubmitted] = useState(false); 376 | const [originalLink, setOriginalLink] = useState(""); 377 | const [originalToken, setOriginalToken] = useState(""); 378 | const [isRunning, setIsRunning] = useState(false); 379 | const intervalRef = useRef(null); 380 | const [lastUpdateTime, setLastUpdateTime] = useState(null); 381 | const [patientData, setPatientData] = useState([]); 382 | 383 | useEffect(() => { 384 | setChartData([]); 385 | }, []); 386 | 387 | const formatTime = (date) => { 388 | if (!date) return ""; 389 | return `${date.getHours().toString().padStart(2, "0")}:${date 390 | .getMinutes() 391 | .toString() 392 | .padStart(2, "0")}:${date.getSeconds().toString().padStart(2, "0")}`; 393 | }; 394 | 395 | /* Sidebar animation variants */ 396 | const sidebarVariants = { 397 | expanded: { width: 280 }, 398 | collapsed: { width: 80 }, 399 | }; 400 | 401 | /* Label show/hide */ 402 | const labelVariants = { 403 | expanded: { opacity: 1, display: "inline" }, 404 | collapsed: { opacity: 0, transitionEnd: { display: "none" } }, 405 | }; 406 | 407 | const riskColors = { 408 | "Low Risk": "#56f589", // Green 409 | "Medium Risk": "#ffed72", // Yellow 410 | "High Risk": "#ff7272", // Red 411 | }; 412 | 413 | const getRiskLevel = (value) => { 414 | if (value < 0.5) return "Low Risk"; 415 | if (value < 0.75) return "Medium Risk"; 416 | return "High Risk"; 417 | }; 418 | 419 | const closeModal = () => { 420 | setModalError(null); 421 | }; 422 | 423 | const validateApiResponse = (data) => { 424 | if (!Array.isArray(data) || data.length === 0) { 425 | return false; 426 | } 427 | 428 | const requiredFields = ["HR", "BP", "SpO2", "RESP", "TEMP", "Patient_ID"]; 429 | for (const row of data) { 430 | for (const field of requiredFields) { 431 | if (!row.hasOwnProperty(field) || row[field] === "") { 432 | return false; 433 | } 434 | } 435 | } 436 | return true; 437 | }; 438 | 439 | const validateInputs = async () => { 440 | if (!link || !token) { 441 | setModalError( 442 | "Please enter both the link and Authorization Bearer token." 443 | ); 444 | return false; 445 | } 446 | 447 | const urlPattern = /^https:\/\/sheetdb\.io\/api\/v1\/([\w\-]+)\/?$/; 448 | if (!urlPattern.test(link)) { 449 | setModalError("Please enter a valid sheetdb.io link."); 450 | return false; 451 | } 452 | 453 | try { 454 | const response = await fetch(link, { 455 | method: "GET", 456 | headers: { 457 | Authorization: `Bearer ${token}`, 458 | }, 459 | }); 460 | if (!response.ok) { 461 | throw new Error("Network response was not ok"); 462 | } 463 | const data = await response.json(); 464 | 465 | if (!validateApiResponse(data)) { 466 | setModalError( 467 | "The data is missing required fields. Please ensure all rows contain HR, BP, SpO2, RESP, TEMP, and Patient_ID." 468 | ); 469 | setLink(""); 470 | setToken(""); 471 | setIsSubmitted(false); 472 | return false; 473 | } 474 | return true; 475 | } catch (error) { 476 | setModalError( 477 | "An error occurred while fetching data. Please check your link and token." 478 | ); 479 | setLink(""); 480 | setToken(""); 481 | setIsSubmitted(false); 482 | return false; 483 | } 484 | }; 485 | 486 | const fetchData = async () => { 487 | try { 488 | const response = await fetch(link, { 489 | method: "GET", 490 | headers: { 491 | Authorization: `Bearer ${token}`, 492 | }, 493 | }); 494 | 495 | if (!response.ok) { 496 | throw new Error("Network response was not ok"); 497 | } 498 | 499 | const data = await response.json(); 500 | 501 | if (!validateApiResponse(data)) { 502 | throw new Error( 503 | "Some of the data is missing required fields or is empty." 504 | ); 505 | } 506 | 507 | const formattedData = data 508 | .map((row) => `${row.HR},${row.BP},${row.SpO2},${row.RESP},${row.TEMP}`) 509 | .join("\n"); 510 | 511 | const result = await varion_backend.prediction_result(formattedData); 512 | 513 | if (!result || !result.Success) { 514 | throw new Error("Invalid response from ML model"); 515 | } 516 | 517 | const predictionValues = result.Success.split(",").map(Number); 518 | 519 | const processedPatientData = data.map((row, index) => ({ 520 | id: row.Patient_ID, 521 | HR: row.HR, 522 | BP: row.BP, 523 | SpO2: row.SpO2, 524 | RESP: row.RESP, 525 | TEMP: row.TEMP, 526 | riskLevel: getRiskLevel(predictionValues[index]), 527 | cardiacProba: predictionValues[index], 528 | lastUpdated: formatTime(new Date()), 529 | })); 530 | 531 | setPatientData(processedPatientData); 532 | 533 | const riskLevelsCount = { 534 | "Low Risk": 0, 535 | "Medium Risk": 0, 536 | "High Risk": 0, 537 | }; 538 | 539 | predictionValues.forEach((val) => { 540 | riskLevelsCount[getRiskLevel(val)]++; 541 | }); 542 | 543 | setChartData([ 544 | { 545 | id: "Risk Levels", 546 | data: [ 547 | { x: "Low Risk", Patients: riskLevelsCount["Low Risk"] }, 548 | { x: "Medium Risk", Patients: riskLevelsCount["Medium Risk"] }, 549 | { x: "High Risk", Patients: riskLevelsCount["High Risk"] }, 550 | ], 551 | }, 552 | ]); 553 | 554 | setLastUpdateTime(new Date()); 555 | } catch (error) { 556 | setModalError(`An error occurred: ${error.message}`); 557 | } 558 | }; 559 | 560 | const handleStartStop = () => { 561 | setIsRunning((prev) => { 562 | if (prev) { 563 | clearInterval(intervalRef.current); 564 | return false; 565 | } 566 | // Start interval 567 | fetchData(); 568 | intervalRef.current = setInterval(fetchData, 10000); 569 | return true; 570 | }); 571 | }; 572 | 573 | const handleSubmit = async () => { 574 | const valid = await validateInputs(); 575 | if (valid) { 576 | setIsSubmitted(true); 577 | setIsEditing(false); 578 | } 579 | }; 580 | 581 | const handleEdit = () => { 582 | setOriginalLink(link); 583 | setOriginalToken(token); 584 | setIsEditing(true); 585 | if (isRunning) handleStartStop(); 586 | }; 587 | 588 | const handleConfirm = async () => { 589 | const valid = await validateInputs(); 590 | if (valid) { 591 | setIsEditing(false); 592 | } 593 | }; 594 | 595 | const handleCancel = () => { 596 | setLink(originalLink); 597 | setToken(originalToken); 598 | setIsEditing(false); 599 | }; 600 | 601 | const handleSignOut = async () => { 602 | if (isSigningOut) return; 603 | setIsSigningOut(true); 604 | try { 605 | await disconnect(); 606 | } catch (e) { 607 | console.error("Error during sign out:", e); 608 | } finally { 609 | setIsSigningOut(false); 610 | } 611 | }; 612 | 613 | const maskedToken = maskToken(token); 614 | 615 | /* Active nav logic */ 616 | const navItems = [ 617 | { key: "dashboard", icon: , label: "Dashboard" }, 618 | { key: "patients", icon: , label: "Patients" }, 619 | { key: "signout", icon: , label: "Sign Out" }, 620 | ]; 621 | 622 | /* Renders */ 623 | const renderComponent = () => { 624 | switch (activeComponent) { 625 | case "dashboard": 626 | return ( 627 | 628 | 629 | Real-time Patient Data Monitoring Dashboard 630 | 631 | 632 | 633 | {lastUpdateTime && ( 634 |

643 | Last updated: {formatTime(lastUpdateTime)} 644 |

645 | )} 646 | {chartData.length > 0 && chartData[0].data.length > 0 ? ( 647 | riskColors[data.x]} 656 | borderColor={{ from: "color", modifiers: [["darker", 1.6]] }} 657 | axisTop={null} 658 | axisRight={null} 659 | axisBottom={{ 660 | tickSize: 5, 661 | tickPadding: 5, 662 | tickRotation: 0, 663 | legend: "Cardiac Risk Level", 664 | legendPosition: "middle", 665 | legendOffset: 40, 666 | }} 667 | axisLeft={{ 668 | tickSize: 5, 669 | tickPadding: 5, 670 | tickRotation: 0, 671 | legend: "Patient Count", 672 | legendPosition: "middle", 673 | legendOffset: -40, 674 | format: (d) => (Number.isInteger(d) ? d : ""), 675 | tickValues: (() => { 676 | const maxPatients = Math.max( 677 | ...chartData[0].data.map((d) => d.Patients) 678 | ); 679 | if (maxPatients <= 10) return undefined; 680 | const interval = Math.ceil(maxPatients / 10); 681 | return Array.from( 682 | { length: Math.floor(maxPatients / interval) + 1 }, 683 | (_, i) => i * interval 684 | ); 685 | })(), 686 | }} 687 | labelSkipWidth={12} 688 | labelSkipHeight={12} 689 | labelTextColor={{ from: "color", modifiers: [["darker", 1.6]] }} 690 | animate={true} 691 | motionStiffness={90} 692 | motionDamping={15} 693 | label={(d) => `${d.value}`} 694 | /> 695 | ) : ( 696 | Data not available 697 | )} 698 |
699 | 700 | 701 | {isSubmitted && !isEditing ? ( 702 | <> 703 | Currently streaming data from: 704 |

705 | Link: {link} 706 |

707 |

708 | Token: {maskedToken} 709 |

710 | 711 | Edit 712 | 713 |
714 | 715 | {isRunning ? "Stop ML Model" : "Start ML Model"} 716 | 717 |
718 | 719 | ) : ( 720 | <> 721 | 722 | Please provide a sheetdb.io link and its 723 | authorization bearer token to access the Spreadsheet: 724 | 725 | 726 | setLink(e.target.value)} 730 | placeholder="Enter Link" 731 | autoComplete="off" 732 | /> 733 | setToken(e.target.value)} 737 | placeholder="Enter Token" 738 | autoComplete="off" 739 | /> 740 | 741 | {isEditing ? ( 742 |
743 | Confirm 744 | Cancel 745 |
746 | ) : ( 747 | 752 | Submit 753 | 754 | )} 755 | 756 | {(!isSubmitted || isEditing) && ( 757 | <> 758 |
766 |

767 | Please format your Google Spreadsheet according to 768 | the following template: 769 |

770 | 797 |
798 | 799 | 800 | 801 | 802 | 803 | A 804 | B 805 | C 806 | D 807 | E 808 | F 809 | 810 | 811 | 812 | 813 | 816 | 817 | HR 818 | 819 | BP 820 | SpO2 821 | RESP 822 | TEMP 823 | Patient_ID 824 | 825 | 826 | 829 | 72 830 | 120 831 | 98 832 | 16 833 | 36.5 834 | 101 835 | 836 | 837 | 840 | 75 841 | 118 842 | 97 843 | 18 844 | 36.7 845 | 102 846 | 847 | 848 | 851 | ... 852 | ... 853 | ... 854 | ... 855 | ... 856 | ... 857 | 858 | 859 | 862 | ... 863 | ... 864 | ... 865 | ... 866 | ... 867 | ... 868 | 869 | 870 | 871 | 872 | HR: Heart Rate, BP: Systolic Blood Pressure, SpO2: Oxygen 873 | Saturation, RESP: Respiration Rate, TEMP: Temperature 874 | 875 | 876 | )} 877 | 878 | )} 879 |
880 |
881 | ); 882 | 883 | case "patients": 884 | return ; 885 | 886 | default: 887 | return ( 888 | 889 |

Dashboard Content

890 |
891 | ); 892 | } 893 | }; 894 | 895 | return ( 896 | <> 897 | 898 | setIsExpanded(true)} 904 | onHoverEnd={() => setIsExpanded(false)} 905 | aria-label="Sidebar navigation" 906 | > 907 | 908 | 909 | {isExpanded ? ( 910 | 921 | ) : ( 922 | 933 | )} 934 | 935 | 936 | 937 | 985 | 986 | 987 | {renderComponent()} 988 | 989 | 990 | 991 | {modalError && ( 992 | 1001 | 1006 | 1012 | 1013 | )} 1014 | 1015 | 1016 | ); 1017 | }; 1018 | 1019 | export default Dashboard; -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "adler2" 7 | version = "2.0.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 10 | 11 | [[package]] 12 | name = "ahash" 13 | version = "0.8.11" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" 16 | dependencies = [ 17 | "cfg-if", 18 | "once_cell", 19 | "version_check", 20 | "zerocopy", 21 | ] 22 | 23 | [[package]] 24 | name = "aho-corasick" 25 | version = "1.1.3" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 28 | dependencies = [ 29 | "memchr", 30 | ] 31 | 32 | [[package]] 33 | name = "anyhow" 34 | version = "1.0.86" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" 37 | 38 | [[package]] 39 | name = "anymap2" 40 | version = "0.13.0" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c" 43 | 44 | [[package]] 45 | name = "arrayvec" 46 | version = "0.5.2" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" 49 | 50 | [[package]] 51 | name = "autocfg" 52 | version = "1.3.0" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" 55 | 56 | [[package]] 57 | name = "binread" 58 | version = "2.2.0" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "16598dfc8e6578e9b597d9910ba2e73618385dc9f4b1d43dd92c349d6be6418f" 61 | dependencies = [ 62 | "binread_derive", 63 | "lazy_static", 64 | "rustversion", 65 | ] 66 | 67 | [[package]] 68 | name = "binread_derive" 69 | version = "2.1.0" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | checksum = "1d9672209df1714ee804b1f4d4f68c8eb2a90b1f7a07acf472f88ce198ef1fed" 72 | dependencies = [ 73 | "either", 74 | "proc-macro2", 75 | "quote", 76 | "syn 1.0.109", 77 | ] 78 | 79 | [[package]] 80 | name = "bit-set" 81 | version = "0.5.3" 82 | source = "registry+https://github.com/rust-lang/crates.io-index" 83 | checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" 84 | dependencies = [ 85 | "bit-vec", 86 | ] 87 | 88 | [[package]] 89 | name = "bit-vec" 90 | version = "0.6.3" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" 93 | 94 | [[package]] 95 | name = "bitflags" 96 | version = "2.6.0" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" 99 | 100 | [[package]] 101 | name = "block-buffer" 102 | version = "0.10.4" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 105 | dependencies = [ 106 | "generic-array", 107 | ] 108 | 109 | [[package]] 110 | name = "byteorder" 111 | version = "1.5.0" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 114 | 115 | [[package]] 116 | name = "bytes" 117 | version = "1.7.1" 118 | source = "registry+https://github.com/rust-lang/crates.io-index" 119 | checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" 120 | 121 | [[package]] 122 | name = "candid" 123 | version = "0.10.10" 124 | source = "registry+https://github.com/rust-lang/crates.io-index" 125 | checksum = "6c30ee7f886f296b6422c0ff017e89dd4f831521dfdcc76f3f71aae1ce817222" 126 | dependencies = [ 127 | "anyhow", 128 | "binread", 129 | "byteorder", 130 | "candid_derive", 131 | "hex", 132 | "ic_principal", 133 | "leb128", 134 | "num-bigint", 135 | "num-traits", 136 | "paste", 137 | "pretty", 138 | "serde", 139 | "serde_bytes", 140 | "stacker", 141 | "thiserror", 142 | ] 143 | 144 | [[package]] 145 | name = "candid_derive" 146 | version = "0.6.6" 147 | source = "registry+https://github.com/rust-lang/crates.io-index" 148 | checksum = "3de398570c386726e7a59d9887b68763c481477f9a043fb998a2e09d428df1a9" 149 | dependencies = [ 150 | "lazy_static", 151 | "proc-macro2", 152 | "quote", 153 | "syn 2.0.76", 154 | ] 155 | 156 | [[package]] 157 | name = "cc" 158 | version = "1.1.14" 159 | source = "registry+https://github.com/rust-lang/crates.io-index" 160 | checksum = "50d2eb3cd3d1bf4529e31c215ee6f93ec5a3d536d9f578f93d9d33ee19562932" 161 | dependencies = [ 162 | "shlex", 163 | ] 164 | 165 | [[package]] 166 | name = "cfg-if" 167 | version = "1.0.0" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 170 | 171 | [[package]] 172 | name = "cpufeatures" 173 | version = "0.2.13" 174 | source = "registry+https://github.com/rust-lang/crates.io-index" 175 | checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" 176 | dependencies = [ 177 | "libc", 178 | ] 179 | 180 | [[package]] 181 | name = "crc32fast" 182 | version = "1.4.2" 183 | source = "registry+https://github.com/rust-lang/crates.io-index" 184 | checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" 185 | dependencies = [ 186 | "cfg-if", 187 | ] 188 | 189 | [[package]] 190 | name = "crossbeam-deque" 191 | version = "0.8.5" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" 194 | dependencies = [ 195 | "crossbeam-epoch", 196 | "crossbeam-utils", 197 | ] 198 | 199 | [[package]] 200 | name = "crossbeam-epoch" 201 | version = "0.9.18" 202 | source = "registry+https://github.com/rust-lang/crates.io-index" 203 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 204 | dependencies = [ 205 | "crossbeam-utils", 206 | ] 207 | 208 | [[package]] 209 | name = "crossbeam-utils" 210 | version = "0.8.20" 211 | source = "registry+https://github.com/rust-lang/crates.io-index" 212 | checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" 213 | 214 | [[package]] 215 | name = "crunchy" 216 | version = "0.2.2" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" 219 | 220 | [[package]] 221 | name = "crypto-common" 222 | version = "0.1.6" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 225 | dependencies = [ 226 | "generic-array", 227 | "typenum", 228 | ] 229 | 230 | [[package]] 231 | name = "data-encoding" 232 | version = "2.6.0" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" 235 | 236 | [[package]] 237 | name = "deranged" 238 | version = "0.3.11" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" 241 | dependencies = [ 242 | "powerfmt", 243 | ] 244 | 245 | [[package]] 246 | name = "derive-new" 247 | version = "0.5.9" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535" 250 | dependencies = [ 251 | "proc-macro2", 252 | "quote", 253 | "syn 1.0.109", 254 | ] 255 | 256 | [[package]] 257 | name = "digest" 258 | version = "0.10.7" 259 | source = "registry+https://github.com/rust-lang/crates.io-index" 260 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 261 | dependencies = [ 262 | "block-buffer", 263 | "crypto-common", 264 | ] 265 | 266 | [[package]] 267 | name = "doc-comment" 268 | version = "0.3.3" 269 | source = "registry+https://github.com/rust-lang/crates.io-index" 270 | checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" 271 | 272 | [[package]] 273 | name = "downcast-rs" 274 | version = "1.2.1" 275 | source = "registry+https://github.com/rust-lang/crates.io-index" 276 | checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" 277 | 278 | [[package]] 279 | name = "dyn-clone" 280 | version = "1.0.17" 281 | source = "registry+https://github.com/rust-lang/crates.io-index" 282 | checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" 283 | 284 | [[package]] 285 | name = "dyn-hash" 286 | version = "0.2.0" 287 | source = "registry+https://github.com/rust-lang/crates.io-index" 288 | checksum = "a650a461c6a8ff1ef205ed9a2ad56579309853fecefc2423f73dced342f92258" 289 | 290 | [[package]] 291 | name = "either" 292 | version = "1.13.0" 293 | source = "registry+https://github.com/rust-lang/crates.io-index" 294 | checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" 295 | 296 | [[package]] 297 | name = "errno" 298 | version = "0.3.9" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" 301 | dependencies = [ 302 | "libc", 303 | "windows-sys 0.52.0", 304 | ] 305 | 306 | [[package]] 307 | name = "filetime" 308 | version = "0.2.24" 309 | source = "registry+https://github.com/rust-lang/crates.io-index" 310 | checksum = "bf401df4a4e3872c4fe8151134cf483738e74b67fc934d6532c882b3d24a4550" 311 | dependencies = [ 312 | "cfg-if", 313 | "libc", 314 | "libredox", 315 | "windows-sys 0.59.0", 316 | ] 317 | 318 | [[package]] 319 | name = "flate2" 320 | version = "1.0.33" 321 | source = "registry+https://github.com/rust-lang/crates.io-index" 322 | checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" 323 | dependencies = [ 324 | "crc32fast", 325 | "miniz_oxide", 326 | ] 327 | 328 | [[package]] 329 | name = "futures" 330 | version = "0.3.30" 331 | source = "registry+https://github.com/rust-lang/crates.io-index" 332 | checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" 333 | dependencies = [ 334 | "futures-channel", 335 | "futures-core", 336 | "futures-executor", 337 | "futures-io", 338 | "futures-sink", 339 | "futures-task", 340 | "futures-util", 341 | ] 342 | 343 | [[package]] 344 | name = "futures-channel" 345 | version = "0.3.30" 346 | source = "registry+https://github.com/rust-lang/crates.io-index" 347 | checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" 348 | dependencies = [ 349 | "futures-core", 350 | "futures-sink", 351 | ] 352 | 353 | [[package]] 354 | name = "futures-core" 355 | version = "0.3.30" 356 | source = "registry+https://github.com/rust-lang/crates.io-index" 357 | checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" 358 | 359 | [[package]] 360 | name = "futures-executor" 361 | version = "0.3.30" 362 | source = "registry+https://github.com/rust-lang/crates.io-index" 363 | checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" 364 | dependencies = [ 365 | "futures-core", 366 | "futures-task", 367 | "futures-util", 368 | ] 369 | 370 | [[package]] 371 | name = "futures-io" 372 | version = "0.3.30" 373 | source = "registry+https://github.com/rust-lang/crates.io-index" 374 | checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" 375 | 376 | [[package]] 377 | name = "futures-macro" 378 | version = "0.3.30" 379 | source = "registry+https://github.com/rust-lang/crates.io-index" 380 | checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" 381 | dependencies = [ 382 | "proc-macro2", 383 | "quote", 384 | "syn 2.0.76", 385 | ] 386 | 387 | [[package]] 388 | name = "futures-sink" 389 | version = "0.3.30" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" 392 | 393 | [[package]] 394 | name = "futures-task" 395 | version = "0.3.30" 396 | source = "registry+https://github.com/rust-lang/crates.io-index" 397 | checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" 398 | 399 | [[package]] 400 | name = "futures-util" 401 | version = "0.3.30" 402 | source = "registry+https://github.com/rust-lang/crates.io-index" 403 | checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" 404 | dependencies = [ 405 | "futures-channel", 406 | "futures-core", 407 | "futures-io", 408 | "futures-macro", 409 | "futures-sink", 410 | "futures-task", 411 | "memchr", 412 | "pin-project-lite", 413 | "pin-utils", 414 | "slab", 415 | ] 416 | 417 | [[package]] 418 | name = "generic-array" 419 | version = "0.14.7" 420 | source = "registry+https://github.com/rust-lang/crates.io-index" 421 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 422 | dependencies = [ 423 | "typenum", 424 | "version_check", 425 | ] 426 | 427 | [[package]] 428 | name = "getrandom" 429 | version = "0.2.15" 430 | source = "registry+https://github.com/rust-lang/crates.io-index" 431 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 432 | dependencies = [ 433 | "cfg-if", 434 | "libc", 435 | "wasi", 436 | ] 437 | 438 | [[package]] 439 | name = "half" 440 | version = "2.4.1" 441 | source = "registry+https://github.com/rust-lang/crates.io-index" 442 | checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" 443 | dependencies = [ 444 | "cfg-if", 445 | "crunchy", 446 | "num-traits", 447 | ] 448 | 449 | [[package]] 450 | name = "hashbrown" 451 | version = "0.14.5" 452 | source = "registry+https://github.com/rust-lang/crates.io-index" 453 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 454 | dependencies = [ 455 | "ahash", 456 | ] 457 | 458 | [[package]] 459 | name = "hex" 460 | version = "0.4.3" 461 | source = "registry+https://github.com/rust-lang/crates.io-index" 462 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 463 | 464 | [[package]] 465 | name = "ic-cdk" 466 | version = "0.13.5" 467 | source = "registry+https://github.com/rust-lang/crates.io-index" 468 | checksum = "3b1da6a25b045f9da3c9459c0cb2b0700ac368ee16382975a17185a23b9c18ab" 469 | dependencies = [ 470 | "candid", 471 | "ic-cdk-macros 0.13.2", 472 | "ic0 0.21.1", 473 | "serde", 474 | "serde_bytes", 475 | ] 476 | 477 | [[package]] 478 | name = "ic-cdk" 479 | version = "0.15.1" 480 | source = "registry+https://github.com/rust-lang/crates.io-index" 481 | checksum = "038ff230bf0fc8630943e3c52e989d248a7c89834ccb65da408fabc5817a475b" 482 | dependencies = [ 483 | "candid", 484 | "ic-cdk-macros 0.15.0", 485 | "ic0 0.23.0", 486 | "serde", 487 | "serde_bytes", 488 | ] 489 | 490 | [[package]] 491 | name = "ic-cdk-macros" 492 | version = "0.13.2" 493 | source = "registry+https://github.com/rust-lang/crates.io-index" 494 | checksum = "a45800053d80a6df839a71aaea5797e723188c0b992618208ca3b941350c7355" 495 | dependencies = [ 496 | "candid", 497 | "proc-macro2", 498 | "quote", 499 | "serde", 500 | "serde_tokenstream 0.1.7", 501 | "syn 1.0.109", 502 | ] 503 | 504 | [[package]] 505 | name = "ic-cdk-macros" 506 | version = "0.15.0" 507 | source = "registry+https://github.com/rust-lang/crates.io-index" 508 | checksum = "3af44fb4ec3a4b18831c9d3303ca8fa2ace846c4022d50cb8df4122635d3782e" 509 | dependencies = [ 510 | "candid", 511 | "proc-macro2", 512 | "quote", 513 | "serde", 514 | "serde_tokenstream 0.2.2", 515 | "syn 2.0.76", 516 | ] 517 | 518 | [[package]] 519 | name = "ic-cdk-timers" 520 | version = "0.7.0" 521 | source = "registry+https://github.com/rust-lang/crates.io-index" 522 | checksum = "054727a3a1c486528b96349817d54290ff70df6addf417def456ea708a16f7fb" 523 | dependencies = [ 524 | "futures", 525 | "ic-cdk 0.13.5", 526 | "ic0 0.21.1", 527 | "serde", 528 | "serde_bytes", 529 | "slotmap", 530 | ] 531 | 532 | [[package]] 533 | name = "ic0" 534 | version = "0.21.1" 535 | source = "registry+https://github.com/rust-lang/crates.io-index" 536 | checksum = "a54b5297861c651551676e8c43df805dad175cc33bc97dbd992edbbb85dcbcdf" 537 | 538 | [[package]] 539 | name = "ic0" 540 | version = "0.23.0" 541 | source = "registry+https://github.com/rust-lang/crates.io-index" 542 | checksum = "8de254dd67bbd58073e23dc1c8553ba12fa1dc610a19de94ad2bbcd0460c067f" 543 | 544 | [[package]] 545 | name = "ic_principal" 546 | version = "0.1.1" 547 | source = "registry+https://github.com/rust-lang/crates.io-index" 548 | checksum = "1762deb6f7c8d8c2bdee4b6c5a47b60195b74e9b5280faa5ba29692f8e17429c" 549 | dependencies = [ 550 | "crc32fast", 551 | "data-encoding", 552 | "serde", 553 | "sha2", 554 | "thiserror", 555 | ] 556 | 557 | [[package]] 558 | name = "itertools" 559 | version = "0.10.5" 560 | source = "registry+https://github.com/rust-lang/crates.io-index" 561 | checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" 562 | dependencies = [ 563 | "either", 564 | ] 565 | 566 | [[package]] 567 | name = "itertools" 568 | version = "0.12.1" 569 | source = "registry+https://github.com/rust-lang/crates.io-index" 570 | checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" 571 | dependencies = [ 572 | "either", 573 | ] 574 | 575 | [[package]] 576 | name = "itertools" 577 | version = "0.13.0" 578 | source = "registry+https://github.com/rust-lang/crates.io-index" 579 | checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" 580 | dependencies = [ 581 | "either", 582 | ] 583 | 584 | [[package]] 585 | name = "itoa" 586 | version = "1.0.11" 587 | source = "registry+https://github.com/rust-lang/crates.io-index" 588 | checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" 589 | 590 | [[package]] 591 | name = "kstring" 592 | version = "2.0.2" 593 | source = "registry+https://github.com/rust-lang/crates.io-index" 594 | checksum = "558bf9508a558512042d3095138b1f7b8fe90c5467d94f9f1da28b3731c5dbd1" 595 | dependencies = [ 596 | "serde", 597 | "static_assertions", 598 | ] 599 | 600 | [[package]] 601 | name = "lazy_static" 602 | version = "1.5.0" 603 | source = "registry+https://github.com/rust-lang/crates.io-index" 604 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 605 | 606 | [[package]] 607 | name = "leb128" 608 | version = "0.2.5" 609 | source = "registry+https://github.com/rust-lang/crates.io-index" 610 | checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" 611 | 612 | [[package]] 613 | name = "libc" 614 | version = "0.2.158" 615 | source = "registry+https://github.com/rust-lang/crates.io-index" 616 | checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" 617 | 618 | [[package]] 619 | name = "libm" 620 | version = "0.2.8" 621 | source = "registry+https://github.com/rust-lang/crates.io-index" 622 | checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" 623 | 624 | [[package]] 625 | name = "libredox" 626 | version = "0.1.3" 627 | source = "registry+https://github.com/rust-lang/crates.io-index" 628 | checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" 629 | dependencies = [ 630 | "bitflags", 631 | "libc", 632 | "redox_syscall", 633 | ] 634 | 635 | [[package]] 636 | name = "linux-raw-sys" 637 | version = "0.4.14" 638 | source = "registry+https://github.com/rust-lang/crates.io-index" 639 | checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" 640 | 641 | [[package]] 642 | name = "liquid" 643 | version = "0.26.9" 644 | source = "registry+https://github.com/rust-lang/crates.io-index" 645 | checksum = "7cdcc72b82748f47c2933c172313f5a9aea5b2c4eb3fa4c66b4ea55bb60bb4b1" 646 | dependencies = [ 647 | "doc-comment", 648 | "liquid-core", 649 | "liquid-derive", 650 | "liquid-lib", 651 | "serde", 652 | ] 653 | 654 | [[package]] 655 | name = "liquid-core" 656 | version = "0.26.9" 657 | source = "registry+https://github.com/rust-lang/crates.io-index" 658 | checksum = "2752e978ffc53670f3f2e8b3ef09f348d6f7b5474a3be3f8a5befe5382e4effb" 659 | dependencies = [ 660 | "anymap2", 661 | "itertools 0.13.0", 662 | "kstring", 663 | "liquid-derive", 664 | "num-traits", 665 | "pest", 666 | "pest_derive", 667 | "regex", 668 | "serde", 669 | "time", 670 | ] 671 | 672 | [[package]] 673 | name = "liquid-derive" 674 | version = "0.26.8" 675 | source = "registry+https://github.com/rust-lang/crates.io-index" 676 | checksum = "3b51f1d220e3fa869e24cfd75915efe3164bd09bb11b3165db3f37f57bf673e3" 677 | dependencies = [ 678 | "proc-macro2", 679 | "quote", 680 | "syn 2.0.76", 681 | ] 682 | 683 | [[package]] 684 | name = "liquid-lib" 685 | version = "0.26.9" 686 | source = "registry+https://github.com/rust-lang/crates.io-index" 687 | checksum = "59b1a298d3d2287ee5b1e43840d885b8fdfc37d3f4e90d82aacfd04d021618da" 688 | dependencies = [ 689 | "itertools 0.13.0", 690 | "liquid-core", 691 | "once_cell", 692 | "percent-encoding", 693 | "regex", 694 | "time", 695 | "unicode-segmentation", 696 | ] 697 | 698 | [[package]] 699 | name = "log" 700 | version = "0.4.22" 701 | source = "registry+https://github.com/rust-lang/crates.io-index" 702 | checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" 703 | 704 | [[package]] 705 | name = "maplit" 706 | version = "1.0.2" 707 | source = "registry+https://github.com/rust-lang/crates.io-index" 708 | checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" 709 | 710 | [[package]] 711 | name = "matrixmultiply" 712 | version = "0.3.9" 713 | source = "registry+https://github.com/rust-lang/crates.io-index" 714 | checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" 715 | dependencies = [ 716 | "autocfg", 717 | "rawpointer", 718 | ] 719 | 720 | [[package]] 721 | name = "memchr" 722 | version = "2.7.4" 723 | source = "registry+https://github.com/rust-lang/crates.io-index" 724 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 725 | 726 | [[package]] 727 | name = "memmap2" 728 | version = "0.9.4" 729 | source = "registry+https://github.com/rust-lang/crates.io-index" 730 | checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" 731 | dependencies = [ 732 | "libc", 733 | ] 734 | 735 | [[package]] 736 | name = "minimal-lexical" 737 | version = "0.2.1" 738 | source = "registry+https://github.com/rust-lang/crates.io-index" 739 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 740 | 741 | [[package]] 742 | name = "miniz_oxide" 743 | version = "0.8.0" 744 | source = "registry+https://github.com/rust-lang/crates.io-index" 745 | checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" 746 | dependencies = [ 747 | "adler2", 748 | ] 749 | 750 | [[package]] 751 | name = "ndarray" 752 | version = "0.15.6" 753 | source = "registry+https://github.com/rust-lang/crates.io-index" 754 | checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32" 755 | dependencies = [ 756 | "matrixmultiply", 757 | "num-complex", 758 | "num-integer", 759 | "num-traits", 760 | "rawpointer", 761 | ] 762 | 763 | [[package]] 764 | name = "nom" 765 | version = "7.1.3" 766 | source = "registry+https://github.com/rust-lang/crates.io-index" 767 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 768 | dependencies = [ 769 | "memchr", 770 | "minimal-lexical", 771 | ] 772 | 773 | [[package]] 774 | name = "num-bigint" 775 | version = "0.4.6" 776 | source = "registry+https://github.com/rust-lang/crates.io-index" 777 | checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" 778 | dependencies = [ 779 | "num-integer", 780 | "num-traits", 781 | "serde", 782 | ] 783 | 784 | [[package]] 785 | name = "num-complex" 786 | version = "0.4.6" 787 | source = "registry+https://github.com/rust-lang/crates.io-index" 788 | checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" 789 | dependencies = [ 790 | "num-traits", 791 | ] 792 | 793 | [[package]] 794 | name = "num-conv" 795 | version = "0.1.0" 796 | source = "registry+https://github.com/rust-lang/crates.io-index" 797 | checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" 798 | 799 | [[package]] 800 | name = "num-integer" 801 | version = "0.1.46" 802 | source = "registry+https://github.com/rust-lang/crates.io-index" 803 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 804 | dependencies = [ 805 | "num-traits", 806 | ] 807 | 808 | [[package]] 809 | name = "num-traits" 810 | version = "0.2.19" 811 | source = "registry+https://github.com/rust-lang/crates.io-index" 812 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 813 | dependencies = [ 814 | "autocfg", 815 | "libm", 816 | ] 817 | 818 | [[package]] 819 | name = "once_cell" 820 | version = "1.19.0" 821 | source = "registry+https://github.com/rust-lang/crates.io-index" 822 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 823 | 824 | [[package]] 825 | name = "paste" 826 | version = "1.0.15" 827 | source = "registry+https://github.com/rust-lang/crates.io-index" 828 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 829 | 830 | [[package]] 831 | name = "percent-encoding" 832 | version = "2.3.1" 833 | source = "registry+https://github.com/rust-lang/crates.io-index" 834 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 835 | 836 | [[package]] 837 | name = "pest" 838 | version = "2.7.11" 839 | source = "registry+https://github.com/rust-lang/crates.io-index" 840 | checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" 841 | dependencies = [ 842 | "memchr", 843 | "thiserror", 844 | "ucd-trie", 845 | ] 846 | 847 | [[package]] 848 | name = "pest_derive" 849 | version = "2.7.11" 850 | source = "registry+https://github.com/rust-lang/crates.io-index" 851 | checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" 852 | dependencies = [ 853 | "pest", 854 | "pest_generator", 855 | ] 856 | 857 | [[package]] 858 | name = "pest_generator" 859 | version = "2.7.11" 860 | source = "registry+https://github.com/rust-lang/crates.io-index" 861 | checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" 862 | dependencies = [ 863 | "pest", 864 | "pest_meta", 865 | "proc-macro2", 866 | "quote", 867 | "syn 2.0.76", 868 | ] 869 | 870 | [[package]] 871 | name = "pest_meta" 872 | version = "2.7.11" 873 | source = "registry+https://github.com/rust-lang/crates.io-index" 874 | checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" 875 | dependencies = [ 876 | "once_cell", 877 | "pest", 878 | "sha2", 879 | ] 880 | 881 | [[package]] 882 | name = "pin-project-lite" 883 | version = "0.2.14" 884 | source = "registry+https://github.com/rust-lang/crates.io-index" 885 | checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" 886 | 887 | [[package]] 888 | name = "pin-utils" 889 | version = "0.1.0" 890 | source = "registry+https://github.com/rust-lang/crates.io-index" 891 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 892 | 893 | [[package]] 894 | name = "powerfmt" 895 | version = "0.2.0" 896 | source = "registry+https://github.com/rust-lang/crates.io-index" 897 | checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" 898 | 899 | [[package]] 900 | name = "ppv-lite86" 901 | version = "0.2.20" 902 | source = "registry+https://github.com/rust-lang/crates.io-index" 903 | checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" 904 | dependencies = [ 905 | "zerocopy", 906 | ] 907 | 908 | [[package]] 909 | name = "pretty" 910 | version = "0.12.3" 911 | source = "registry+https://github.com/rust-lang/crates.io-index" 912 | checksum = "b55c4d17d994b637e2f4daf6e5dc5d660d209d5642377d675d7a1c3ab69fa579" 913 | dependencies = [ 914 | "arrayvec", 915 | "typed-arena", 916 | "unicode-width", 917 | ] 918 | 919 | [[package]] 920 | name = "primal-check" 921 | version = "0.3.4" 922 | source = "registry+https://github.com/rust-lang/crates.io-index" 923 | checksum = "dc0d895b311e3af9902528fbb8f928688abbd95872819320517cc24ca6b2bd08" 924 | dependencies = [ 925 | "num-integer", 926 | ] 927 | 928 | [[package]] 929 | name = "proc-macro2" 930 | version = "1.0.86" 931 | source = "registry+https://github.com/rust-lang/crates.io-index" 932 | checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" 933 | dependencies = [ 934 | "unicode-ident", 935 | ] 936 | 937 | [[package]] 938 | name = "prost" 939 | version = "0.11.9" 940 | source = "registry+https://github.com/rust-lang/crates.io-index" 941 | checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" 942 | dependencies = [ 943 | "bytes", 944 | "prost-derive", 945 | ] 946 | 947 | [[package]] 948 | name = "prost-derive" 949 | version = "0.11.9" 950 | source = "registry+https://github.com/rust-lang/crates.io-index" 951 | checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" 952 | dependencies = [ 953 | "anyhow", 954 | "itertools 0.10.5", 955 | "proc-macro2", 956 | "quote", 957 | "syn 1.0.109", 958 | ] 959 | 960 | [[package]] 961 | name = "psm" 962 | version = "0.1.21" 963 | source = "registry+https://github.com/rust-lang/crates.io-index" 964 | checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" 965 | dependencies = [ 966 | "cc", 967 | ] 968 | 969 | [[package]] 970 | name = "quote" 971 | version = "1.0.37" 972 | source = "registry+https://github.com/rust-lang/crates.io-index" 973 | checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" 974 | dependencies = [ 975 | "proc-macro2", 976 | ] 977 | 978 | [[package]] 979 | name = "rand" 980 | version = "0.8.5" 981 | source = "registry+https://github.com/rust-lang/crates.io-index" 982 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 983 | dependencies = [ 984 | "libc", 985 | "rand_chacha", 986 | "rand_core", 987 | ] 988 | 989 | [[package]] 990 | name = "rand_chacha" 991 | version = "0.3.1" 992 | source = "registry+https://github.com/rust-lang/crates.io-index" 993 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 994 | dependencies = [ 995 | "ppv-lite86", 996 | "rand_core", 997 | ] 998 | 999 | [[package]] 1000 | name = "rand_core" 1001 | version = "0.6.4" 1002 | source = "registry+https://github.com/rust-lang/crates.io-index" 1003 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1004 | dependencies = [ 1005 | "getrandom", 1006 | ] 1007 | 1008 | [[package]] 1009 | name = "rand_distr" 1010 | version = "0.4.3" 1011 | source = "registry+https://github.com/rust-lang/crates.io-index" 1012 | checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" 1013 | dependencies = [ 1014 | "num-traits", 1015 | "rand", 1016 | ] 1017 | 1018 | [[package]] 1019 | name = "rawpointer" 1020 | version = "0.2.1" 1021 | source = "registry+https://github.com/rust-lang/crates.io-index" 1022 | checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" 1023 | 1024 | [[package]] 1025 | name = "rayon" 1026 | version = "1.10.0" 1027 | source = "registry+https://github.com/rust-lang/crates.io-index" 1028 | checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" 1029 | dependencies = [ 1030 | "either", 1031 | "rayon-core", 1032 | ] 1033 | 1034 | [[package]] 1035 | name = "rayon-core" 1036 | version = "1.12.1" 1037 | source = "registry+https://github.com/rust-lang/crates.io-index" 1038 | checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" 1039 | dependencies = [ 1040 | "crossbeam-deque", 1041 | "crossbeam-utils", 1042 | ] 1043 | 1044 | [[package]] 1045 | name = "redox_syscall" 1046 | version = "0.5.3" 1047 | source = "registry+https://github.com/rust-lang/crates.io-index" 1048 | checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" 1049 | dependencies = [ 1050 | "bitflags", 1051 | ] 1052 | 1053 | [[package]] 1054 | name = "regex" 1055 | version = "1.10.6" 1056 | source = "registry+https://github.com/rust-lang/crates.io-index" 1057 | checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" 1058 | dependencies = [ 1059 | "aho-corasick", 1060 | "memchr", 1061 | "regex-automata", 1062 | "regex-syntax", 1063 | ] 1064 | 1065 | [[package]] 1066 | name = "regex-automata" 1067 | version = "0.4.7" 1068 | source = "registry+https://github.com/rust-lang/crates.io-index" 1069 | checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" 1070 | dependencies = [ 1071 | "aho-corasick", 1072 | "memchr", 1073 | "regex-syntax", 1074 | ] 1075 | 1076 | [[package]] 1077 | name = "regex-syntax" 1078 | version = "0.8.4" 1079 | source = "registry+https://github.com/rust-lang/crates.io-index" 1080 | checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" 1081 | 1082 | [[package]] 1083 | name = "rustfft" 1084 | version = "6.2.0" 1085 | source = "registry+https://github.com/rust-lang/crates.io-index" 1086 | checksum = "43806561bc506d0c5d160643ad742e3161049ac01027b5e6d7524091fd401d86" 1087 | dependencies = [ 1088 | "num-complex", 1089 | "num-integer", 1090 | "num-traits", 1091 | "primal-check", 1092 | "strength_reduce", 1093 | "transpose", 1094 | "version_check", 1095 | ] 1096 | 1097 | [[package]] 1098 | name = "rustix" 1099 | version = "0.38.34" 1100 | source = "registry+https://github.com/rust-lang/crates.io-index" 1101 | checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" 1102 | dependencies = [ 1103 | "bitflags", 1104 | "errno", 1105 | "libc", 1106 | "linux-raw-sys", 1107 | "windows-sys 0.52.0", 1108 | ] 1109 | 1110 | [[package]] 1111 | name = "rustversion" 1112 | version = "1.0.17" 1113 | source = "registry+https://github.com/rust-lang/crates.io-index" 1114 | checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" 1115 | 1116 | [[package]] 1117 | name = "same-file" 1118 | version = "1.0.6" 1119 | source = "registry+https://github.com/rust-lang/crates.io-index" 1120 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 1121 | dependencies = [ 1122 | "winapi-util", 1123 | ] 1124 | 1125 | [[package]] 1126 | name = "scan_fmt" 1127 | version = "0.2.6" 1128 | source = "registry+https://github.com/rust-lang/crates.io-index" 1129 | checksum = "0b53b0a5db882a8e2fdaae0a43f7b39e7e9082389e978398bdf223a55b581248" 1130 | dependencies = [ 1131 | "regex", 1132 | ] 1133 | 1134 | [[package]] 1135 | name = "serde" 1136 | version = "1.0.209" 1137 | source = "registry+https://github.com/rust-lang/crates.io-index" 1138 | checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" 1139 | dependencies = [ 1140 | "serde_derive", 1141 | ] 1142 | 1143 | [[package]] 1144 | name = "serde_bytes" 1145 | version = "0.11.15" 1146 | source = "registry+https://github.com/rust-lang/crates.io-index" 1147 | checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" 1148 | dependencies = [ 1149 | "serde", 1150 | ] 1151 | 1152 | [[package]] 1153 | name = "serde_derive" 1154 | version = "1.0.209" 1155 | source = "registry+https://github.com/rust-lang/crates.io-index" 1156 | checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" 1157 | dependencies = [ 1158 | "proc-macro2", 1159 | "quote", 1160 | "syn 2.0.76", 1161 | ] 1162 | 1163 | [[package]] 1164 | name = "serde_tokenstream" 1165 | version = "0.1.7" 1166 | source = "registry+https://github.com/rust-lang/crates.io-index" 1167 | checksum = "797ba1d80299b264f3aac68ab5d12e5825a561749db4df7cd7c8083900c5d4e9" 1168 | dependencies = [ 1169 | "proc-macro2", 1170 | "serde", 1171 | "syn 1.0.109", 1172 | ] 1173 | 1174 | [[package]] 1175 | name = "serde_tokenstream" 1176 | version = "0.2.2" 1177 | source = "registry+https://github.com/rust-lang/crates.io-index" 1178 | checksum = "64060d864397305347a78851c51588fd283767e7e7589829e8121d65512340f1" 1179 | dependencies = [ 1180 | "proc-macro2", 1181 | "quote", 1182 | "serde", 1183 | "syn 2.0.76", 1184 | ] 1185 | 1186 | [[package]] 1187 | name = "sha2" 1188 | version = "0.10.8" 1189 | source = "registry+https://github.com/rust-lang/crates.io-index" 1190 | checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" 1191 | dependencies = [ 1192 | "cfg-if", 1193 | "cpufeatures", 1194 | "digest", 1195 | ] 1196 | 1197 | [[package]] 1198 | name = "shlex" 1199 | version = "1.3.0" 1200 | source = "registry+https://github.com/rust-lang/crates.io-index" 1201 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 1202 | 1203 | [[package]] 1204 | name = "slab" 1205 | version = "0.4.9" 1206 | source = "registry+https://github.com/rust-lang/crates.io-index" 1207 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 1208 | dependencies = [ 1209 | "autocfg", 1210 | ] 1211 | 1212 | [[package]] 1213 | name = "slotmap" 1214 | version = "1.0.7" 1215 | source = "registry+https://github.com/rust-lang/crates.io-index" 1216 | checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" 1217 | dependencies = [ 1218 | "version_check", 1219 | ] 1220 | 1221 | [[package]] 1222 | name = "smallvec" 1223 | version = "1.13.2" 1224 | source = "registry+https://github.com/rust-lang/crates.io-index" 1225 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 1226 | 1227 | [[package]] 1228 | name = "stacker" 1229 | version = "0.1.16" 1230 | source = "registry+https://github.com/rust-lang/crates.io-index" 1231 | checksum = "95a5daa25ea337c85ed954c0496e3bdd2c7308cc3b24cf7b50d04876654c579f" 1232 | dependencies = [ 1233 | "cc", 1234 | "cfg-if", 1235 | "libc", 1236 | "psm", 1237 | "windows-sys 0.36.1", 1238 | ] 1239 | 1240 | [[package]] 1241 | name = "static_assertions" 1242 | version = "1.1.0" 1243 | source = "registry+https://github.com/rust-lang/crates.io-index" 1244 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 1245 | 1246 | [[package]] 1247 | name = "strength_reduce" 1248 | version = "0.2.4" 1249 | source = "registry+https://github.com/rust-lang/crates.io-index" 1250 | checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" 1251 | 1252 | [[package]] 1253 | name = "string-interner" 1254 | version = "0.15.0" 1255 | source = "registry+https://github.com/rust-lang/crates.io-index" 1256 | checksum = "07f9fdfdd31a0ff38b59deb401be81b73913d76c9cc5b1aed4e1330a223420b9" 1257 | dependencies = [ 1258 | "cfg-if", 1259 | "hashbrown", 1260 | "serde", 1261 | ] 1262 | 1263 | [[package]] 1264 | name = "syn" 1265 | version = "1.0.109" 1266 | source = "registry+https://github.com/rust-lang/crates.io-index" 1267 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 1268 | dependencies = [ 1269 | "proc-macro2", 1270 | "quote", 1271 | "unicode-ident", 1272 | ] 1273 | 1274 | [[package]] 1275 | name = "syn" 1276 | version = "2.0.76" 1277 | source = "registry+https://github.com/rust-lang/crates.io-index" 1278 | checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525" 1279 | dependencies = [ 1280 | "proc-macro2", 1281 | "quote", 1282 | "unicode-ident", 1283 | ] 1284 | 1285 | [[package]] 1286 | name = "tar" 1287 | version = "0.4.41" 1288 | source = "registry+https://github.com/rust-lang/crates.io-index" 1289 | checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909" 1290 | dependencies = [ 1291 | "filetime", 1292 | "libc", 1293 | "xattr", 1294 | ] 1295 | 1296 | [[package]] 1297 | name = "thiserror" 1298 | version = "1.0.63" 1299 | source = "registry+https://github.com/rust-lang/crates.io-index" 1300 | checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" 1301 | dependencies = [ 1302 | "thiserror-impl", 1303 | ] 1304 | 1305 | [[package]] 1306 | name = "thiserror-impl" 1307 | version = "1.0.63" 1308 | source = "registry+https://github.com/rust-lang/crates.io-index" 1309 | checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" 1310 | dependencies = [ 1311 | "proc-macro2", 1312 | "quote", 1313 | "syn 2.0.76", 1314 | ] 1315 | 1316 | [[package]] 1317 | name = "time" 1318 | version = "0.3.36" 1319 | source = "registry+https://github.com/rust-lang/crates.io-index" 1320 | checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" 1321 | dependencies = [ 1322 | "deranged", 1323 | "itoa", 1324 | "num-conv", 1325 | "powerfmt", 1326 | "serde", 1327 | "time-core", 1328 | "time-macros", 1329 | ] 1330 | 1331 | [[package]] 1332 | name = "time-core" 1333 | version = "0.1.2" 1334 | source = "registry+https://github.com/rust-lang/crates.io-index" 1335 | checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" 1336 | 1337 | [[package]] 1338 | name = "time-macros" 1339 | version = "0.2.18" 1340 | source = "registry+https://github.com/rust-lang/crates.io-index" 1341 | checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" 1342 | dependencies = [ 1343 | "num-conv", 1344 | "time-core", 1345 | ] 1346 | 1347 | [[package]] 1348 | name = "tinyvec" 1349 | version = "1.8.0" 1350 | source = "registry+https://github.com/rust-lang/crates.io-index" 1351 | checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" 1352 | dependencies = [ 1353 | "tinyvec_macros", 1354 | ] 1355 | 1356 | [[package]] 1357 | name = "tinyvec_macros" 1358 | version = "0.1.1" 1359 | source = "registry+https://github.com/rust-lang/crates.io-index" 1360 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 1361 | 1362 | [[package]] 1363 | name = "tract-core" 1364 | version = "0.21.6-pre" 1365 | source = "git+https://github.com/sonos/tract?rev=2a2914ac29390cc08963301c9f3d437b52dd321a#2a2914ac29390cc08963301c9f3d437b52dd321a" 1366 | dependencies = [ 1367 | "anyhow", 1368 | "bit-set", 1369 | "derive-new", 1370 | "downcast-rs", 1371 | "dyn-clone", 1372 | "lazy_static", 1373 | "log", 1374 | "maplit", 1375 | "ndarray", 1376 | "num-complex", 1377 | "num-integer", 1378 | "num-traits", 1379 | "paste", 1380 | "rustfft", 1381 | "smallvec", 1382 | "tract-data", 1383 | "tract-linalg", 1384 | ] 1385 | 1386 | [[package]] 1387 | name = "tract-data" 1388 | version = "0.21.6-pre" 1389 | source = "git+https://github.com/sonos/tract?rev=2a2914ac29390cc08963301c9f3d437b52dd321a#2a2914ac29390cc08963301c9f3d437b52dd321a" 1390 | dependencies = [ 1391 | "anyhow", 1392 | "downcast-rs", 1393 | "dyn-hash", 1394 | "half", 1395 | "itertools 0.12.1", 1396 | "lazy_static", 1397 | "maplit", 1398 | "ndarray", 1399 | "nom", 1400 | "num-integer", 1401 | "num-traits", 1402 | "scan_fmt", 1403 | "smallvec", 1404 | "string-interner", 1405 | ] 1406 | 1407 | [[package]] 1408 | name = "tract-hir" 1409 | version = "0.21.6-pre" 1410 | source = "git+https://github.com/sonos/tract?rev=2a2914ac29390cc08963301c9f3d437b52dd321a#2a2914ac29390cc08963301c9f3d437b52dd321a" 1411 | dependencies = [ 1412 | "derive-new", 1413 | "log", 1414 | "tract-core", 1415 | ] 1416 | 1417 | [[package]] 1418 | name = "tract-linalg" 1419 | version = "0.21.6-pre" 1420 | source = "git+https://github.com/sonos/tract?rev=2a2914ac29390cc08963301c9f3d437b52dd321a#2a2914ac29390cc08963301c9f3d437b52dd321a" 1421 | dependencies = [ 1422 | "cc", 1423 | "derive-new", 1424 | "downcast-rs", 1425 | "dyn-clone", 1426 | "dyn-hash", 1427 | "half", 1428 | "lazy_static", 1429 | "liquid", 1430 | "liquid-core", 1431 | "log", 1432 | "num-traits", 1433 | "paste", 1434 | "rayon", 1435 | "scan_fmt", 1436 | "smallvec", 1437 | "time", 1438 | "tract-data", 1439 | "unicode-normalization", 1440 | "walkdir", 1441 | ] 1442 | 1443 | [[package]] 1444 | name = "tract-nnef" 1445 | version = "0.21.6-pre" 1446 | source = "git+https://github.com/sonos/tract?rev=2a2914ac29390cc08963301c9f3d437b52dd321a#2a2914ac29390cc08963301c9f3d437b52dd321a" 1447 | dependencies = [ 1448 | "byteorder", 1449 | "flate2", 1450 | "log", 1451 | "nom", 1452 | "tar", 1453 | "tract-core", 1454 | "walkdir", 1455 | ] 1456 | 1457 | [[package]] 1458 | name = "tract-onnx" 1459 | version = "0.21.6-pre" 1460 | source = "git+https://github.com/sonos/tract?rev=2a2914ac29390cc08963301c9f3d437b52dd321a#2a2914ac29390cc08963301c9f3d437b52dd321a" 1461 | dependencies = [ 1462 | "bytes", 1463 | "derive-new", 1464 | "log", 1465 | "memmap2", 1466 | "num-integer", 1467 | "prost", 1468 | "smallvec", 1469 | "tract-hir", 1470 | "tract-nnef", 1471 | "tract-onnx-opl", 1472 | ] 1473 | 1474 | [[package]] 1475 | name = "tract-onnx-opl" 1476 | version = "0.21.6-pre" 1477 | source = "git+https://github.com/sonos/tract?rev=2a2914ac29390cc08963301c9f3d437b52dd321a#2a2914ac29390cc08963301c9f3d437b52dd321a" 1478 | dependencies = [ 1479 | "getrandom", 1480 | "log", 1481 | "rand", 1482 | "rand_distr", 1483 | "rustfft", 1484 | "tract-nnef", 1485 | ] 1486 | 1487 | [[package]] 1488 | name = "transpose" 1489 | version = "0.2.3" 1490 | source = "registry+https://github.com/rust-lang/crates.io-index" 1491 | checksum = "1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e" 1492 | dependencies = [ 1493 | "num-integer", 1494 | "strength_reduce", 1495 | ] 1496 | 1497 | [[package]] 1498 | name = "typed-arena" 1499 | version = "2.0.2" 1500 | source = "registry+https://github.com/rust-lang/crates.io-index" 1501 | checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" 1502 | 1503 | [[package]] 1504 | name = "typenum" 1505 | version = "1.17.0" 1506 | source = "registry+https://github.com/rust-lang/crates.io-index" 1507 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" 1508 | 1509 | [[package]] 1510 | name = "ucd-trie" 1511 | version = "0.1.6" 1512 | source = "registry+https://github.com/rust-lang/crates.io-index" 1513 | checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" 1514 | 1515 | [[package]] 1516 | name = "unicode-ident" 1517 | version = "1.0.12" 1518 | source = "registry+https://github.com/rust-lang/crates.io-index" 1519 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 1520 | 1521 | [[package]] 1522 | name = "unicode-normalization" 1523 | version = "0.1.23" 1524 | source = "registry+https://github.com/rust-lang/crates.io-index" 1525 | checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" 1526 | dependencies = [ 1527 | "tinyvec", 1528 | ] 1529 | 1530 | [[package]] 1531 | name = "unicode-segmentation" 1532 | version = "1.11.0" 1533 | source = "registry+https://github.com/rust-lang/crates.io-index" 1534 | checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" 1535 | 1536 | [[package]] 1537 | name = "unicode-width" 1538 | version = "0.1.13" 1539 | source = "registry+https://github.com/rust-lang/crates.io-index" 1540 | checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" 1541 | 1542 | [[package]] 1543 | name = "varion_backend" 1544 | version = "0.1.0" 1545 | dependencies = [ 1546 | "bytes", 1547 | "candid", 1548 | "getrandom", 1549 | "ic-cdk 0.15.1", 1550 | "ic-cdk-macros 0.15.0", 1551 | "ic-cdk-timers", 1552 | "prost", 1553 | "serde", 1554 | "tract-onnx", 1555 | ] 1556 | 1557 | [[package]] 1558 | name = "version_check" 1559 | version = "0.9.5" 1560 | source = "registry+https://github.com/rust-lang/crates.io-index" 1561 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 1562 | 1563 | [[package]] 1564 | name = "walkdir" 1565 | version = "2.5.0" 1566 | source = "registry+https://github.com/rust-lang/crates.io-index" 1567 | checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 1568 | dependencies = [ 1569 | "same-file", 1570 | "winapi-util", 1571 | ] 1572 | 1573 | [[package]] 1574 | name = "wasi" 1575 | version = "0.11.0+wasi-snapshot-preview1" 1576 | source = "registry+https://github.com/rust-lang/crates.io-index" 1577 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1578 | 1579 | [[package]] 1580 | name = "winapi-util" 1581 | version = "0.1.9" 1582 | source = "registry+https://github.com/rust-lang/crates.io-index" 1583 | checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" 1584 | dependencies = [ 1585 | "windows-sys 0.59.0", 1586 | ] 1587 | 1588 | [[package]] 1589 | name = "windows-sys" 1590 | version = "0.36.1" 1591 | source = "registry+https://github.com/rust-lang/crates.io-index" 1592 | checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" 1593 | dependencies = [ 1594 | "windows_aarch64_msvc 0.36.1", 1595 | "windows_i686_gnu 0.36.1", 1596 | "windows_i686_msvc 0.36.1", 1597 | "windows_x86_64_gnu 0.36.1", 1598 | "windows_x86_64_msvc 0.36.1", 1599 | ] 1600 | 1601 | [[package]] 1602 | name = "windows-sys" 1603 | version = "0.52.0" 1604 | source = "registry+https://github.com/rust-lang/crates.io-index" 1605 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 1606 | dependencies = [ 1607 | "windows-targets", 1608 | ] 1609 | 1610 | [[package]] 1611 | name = "windows-sys" 1612 | version = "0.59.0" 1613 | source = "registry+https://github.com/rust-lang/crates.io-index" 1614 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 1615 | dependencies = [ 1616 | "windows-targets", 1617 | ] 1618 | 1619 | [[package]] 1620 | name = "windows-targets" 1621 | version = "0.52.6" 1622 | source = "registry+https://github.com/rust-lang/crates.io-index" 1623 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 1624 | dependencies = [ 1625 | "windows_aarch64_gnullvm", 1626 | "windows_aarch64_msvc 0.52.6", 1627 | "windows_i686_gnu 0.52.6", 1628 | "windows_i686_gnullvm", 1629 | "windows_i686_msvc 0.52.6", 1630 | "windows_x86_64_gnu 0.52.6", 1631 | "windows_x86_64_gnullvm", 1632 | "windows_x86_64_msvc 0.52.6", 1633 | ] 1634 | 1635 | [[package]] 1636 | name = "windows_aarch64_gnullvm" 1637 | version = "0.52.6" 1638 | source = "registry+https://github.com/rust-lang/crates.io-index" 1639 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 1640 | 1641 | [[package]] 1642 | name = "windows_aarch64_msvc" 1643 | version = "0.36.1" 1644 | source = "registry+https://github.com/rust-lang/crates.io-index" 1645 | checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" 1646 | 1647 | [[package]] 1648 | name = "windows_aarch64_msvc" 1649 | version = "0.52.6" 1650 | source = "registry+https://github.com/rust-lang/crates.io-index" 1651 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 1652 | 1653 | [[package]] 1654 | name = "windows_i686_gnu" 1655 | version = "0.36.1" 1656 | source = "registry+https://github.com/rust-lang/crates.io-index" 1657 | checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" 1658 | 1659 | [[package]] 1660 | name = "windows_i686_gnu" 1661 | version = "0.52.6" 1662 | source = "registry+https://github.com/rust-lang/crates.io-index" 1663 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 1664 | 1665 | [[package]] 1666 | name = "windows_i686_gnullvm" 1667 | version = "0.52.6" 1668 | source = "registry+https://github.com/rust-lang/crates.io-index" 1669 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 1670 | 1671 | [[package]] 1672 | name = "windows_i686_msvc" 1673 | version = "0.36.1" 1674 | source = "registry+https://github.com/rust-lang/crates.io-index" 1675 | checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" 1676 | 1677 | [[package]] 1678 | name = "windows_i686_msvc" 1679 | version = "0.52.6" 1680 | source = "registry+https://github.com/rust-lang/crates.io-index" 1681 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 1682 | 1683 | [[package]] 1684 | name = "windows_x86_64_gnu" 1685 | version = "0.36.1" 1686 | source = "registry+https://github.com/rust-lang/crates.io-index" 1687 | checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" 1688 | 1689 | [[package]] 1690 | name = "windows_x86_64_gnu" 1691 | version = "0.52.6" 1692 | source = "registry+https://github.com/rust-lang/crates.io-index" 1693 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 1694 | 1695 | [[package]] 1696 | name = "windows_x86_64_gnullvm" 1697 | version = "0.52.6" 1698 | source = "registry+https://github.com/rust-lang/crates.io-index" 1699 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 1700 | 1701 | [[package]] 1702 | name = "windows_x86_64_msvc" 1703 | version = "0.36.1" 1704 | source = "registry+https://github.com/rust-lang/crates.io-index" 1705 | checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" 1706 | 1707 | [[package]] 1708 | name = "windows_x86_64_msvc" 1709 | version = "0.52.6" 1710 | source = "registry+https://github.com/rust-lang/crates.io-index" 1711 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 1712 | 1713 | [[package]] 1714 | name = "xattr" 1715 | version = "1.3.1" 1716 | source = "registry+https://github.com/rust-lang/crates.io-index" 1717 | checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" 1718 | dependencies = [ 1719 | "libc", 1720 | "linux-raw-sys", 1721 | "rustix", 1722 | ] 1723 | 1724 | [[package]] 1725 | name = "zerocopy" 1726 | version = "0.7.35" 1727 | source = "registry+https://github.com/rust-lang/crates.io-index" 1728 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 1729 | dependencies = [ 1730 | "byteorder", 1731 | "zerocopy-derive", 1732 | ] 1733 | 1734 | [[package]] 1735 | name = "zerocopy-derive" 1736 | version = "0.7.35" 1737 | source = "registry+https://github.com/rust-lang/crates.io-index" 1738 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 1739 | dependencies = [ 1740 | "proc-macro2", 1741 | "quote", 1742 | "syn 2.0.76", 1743 | ] 1744 | --------------------------------------------------------------------------------