From cddf92e43202378076fb3e0ddeaa1dd314c312ba Mon Sep 17 00:00:00 2001
From: SikongJueluo <selfconfusion@gmail.com>
Date: Sat, 29 Mar 2025 13:05:01 +0800
Subject: [PATCH] init branch

---
 flake.nix               |   5 +
 server/common.test.ts   |  66 ------
 server/common.ts        | 191 ----------------
 server/database.test.ts |  65 ------
 server/database.ts      | 478 ----------------------------------------
 server/index.ts         |  21 --
 server/msgBus.ts        |   1 -
 server/msgProtocol.ts   |  79 -------
 server/router.ts        |  12 -
 server/trpc.ts          |   6 -
 server/udp.test.ts      |  22 --
 server/udp.ts           |  80 -------
 server/udpClient.ts     |  17 --
 server/udpProtocol.ts   | 201 -----------------
 server/udpServer.ts     |  97 --------
 tsconfig.bun.json       |  26 ---
 16 files changed, 5 insertions(+), 1362 deletions(-)
 delete mode 100644 server/common.test.ts
 delete mode 100644 server/common.ts
 delete mode 100644 server/database.test.ts
 delete mode 100644 server/database.ts
 delete mode 100644 server/index.ts
 delete mode 100644 server/msgBus.ts
 delete mode 100644 server/msgProtocol.ts
 delete mode 100644 server/router.ts
 delete mode 100644 server/trpc.ts
 delete mode 100644 server/udp.test.ts
 delete mode 100644 server/udp.ts
 delete mode 100644 server/udpClient.ts
 delete mode 100644 server/udpProtocol.ts
 delete mode 100644 server/udpServer.ts
 delete mode 100644 tsconfig.bun.json

diff --git a/flake.nix b/flake.nix
index 0446250..ca9c993 100644
--- a/flake.nix
+++ b/flake.nix
@@ -14,10 +14,15 @@
       devShells = forEachSupportedSystem ({ pkgs }: {
         default = pkgs.mkShell {
           packages = with pkgs; [ 
+            # Frontend
             bun
             sqlite
             sqls
             sql-studio
+            # Backend
+            dotnetCorePackages.sdk_9_0
+            dotnetCorePackages.aspnetcore_9_0
+            nuget
 
             # LSP
             typescript-language-server
diff --git a/server/common.test.ts b/server/common.test.ts
deleted file mode 100644
index 1a513d0..0000000
--- a/server/common.test.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-import { type } from "./common"
-import _ from "lodash"
-import { expect, test } from "bun:test"
-
-const CYCLES = 10000
-test("Test Integer and Unsigned Integer", () => {
-  for (let i = 0; i < CYCLES; i++) {
-
-    // Unsigned Integer
-    expect(type.UInteger.safeParse(_.random(0, Math.pow(2, 53), false)).success).toBeTrue()
-    expect(type.UInt8.safeParse(_.random(0, Math.pow(2, 8) - 1, false)).success).toBeTrue()
-    expect(type.UInt8.safeParse(_.random(Math.pow(2, 8), Math.pow(2, 53), false)).success).toBeFalse()
-    expect(type.UInt16.safeParse(_.random(0, Math.pow(2, 16) - 1, false)).success).toBeTrue()
-    expect(type.UInt16.safeParse(_.random(Math.pow(2, 16), Math.pow(2, 53), false)).success).toBeFalse()
-    expect(type.UInt32.safeParse(_.random(0, Math.pow(2, 32) - 1, false)).success).toBeTrue()
-    expect(type.UInt32.safeParse(_.random(Math.pow(2, 32), Math.pow(2, 53), false)).success).toBeFalse()
-
-    // Integer
-    expect(type.Integer.safeParse(_.random(-Math.pow(2, 52), Math.pow(2, 52) - 1, false)).success).toBeTrue()
-    expect(type.Int8.safeParse(_.random(-Math.pow(2, 7), Math.pow(2, 7) - 1, false)).success).toBeTrue()
-    expect(type.Int8.safeParse(_.random(Math.pow(2, 7), Math.pow(2, 52), false)).success).toBeFalse()
-    expect(type.Int8.safeParse(_.random(-Math.pow(2, 52), -Math.pow(2, 7) - 1, false)).success).toBeFalse()
-    expect(type.Int16.safeParse(_.random(-Math.pow(2, 15), Math.pow(2, 15) - 1, false)).success).toBeTrue()
-    expect(type.Int16.safeParse(_.random(Math.pow(2, 15), Math.pow(2, 52), false)).success).toBeFalse()
-    expect(type.Int16.safeParse(_.random(-Math.pow(2, 52), -Math.pow(2, 15) - 1, false)).success).toBeFalse()
-    expect(type.Int32.safeParse(_.random(-Math.pow(2, 31), Math.pow(2, 31) - 1, false)).success).toBeTrue()
-    expect(type.Int32.safeParse(_.random(Math.pow(2, 31), Math.pow(2, 52), false)).success).toBeFalse()
-    expect(type.Int32.safeParse(_.random(-Math.pow(2, 52), -Math.pow(2, 31) - 1, false)).success).toBeFalse()
-  }
-})
-
-test("Test Number Processor Function", () => {
-  // Convert Number to Uint8Array
-  expect(type.numberToBytes(0xFF, 1).unwrap()[0]).toBe(255)
-  expect(type.numberToBytes(0xAAAA, 2).unwrap()).toEqual(new Uint8Array([0xAA, 0xAA]))
-  expect(type.numberToBytes(0x12345678, 4).unwrap()).toEqual(new Uint8Array([0x78, 0x56, 0x34, 0x12]))
-  expect(type.numberToBytes(0x12345678, 4, true).unwrap()).toEqual(new Uint8Array([0x12, 0x34, 0x56, 0x78]))
-
-  // Convert Uint8Array to Number
-  expect(type.bytesToNumber(new Uint8Array([0xFF]))).toBe(255)
-  expect(type.bytesToNumber(new Uint8Array([0xAA, 0xAA]))).toEqual(0xAAAA)
-  expect(type.bytesToNumber(new Uint8Array([0x78, 0x56, 0x34, 0x12]))).toEqual(0x12345678)
-  expect(type.bytesToNumber(new Uint8Array([0x12, 0x34, 0x56, 0x78]), true)).toEqual(0x12345678)
-
-
-  // Number Match 
-  for (let i = 0; i < CYCLES; i++) {
-    const num1 = _.random(CYCLES / 2, false)
-    const num2 = _.random(CYCLES / 2, false)
-
-    expect(type.numberMatch(num1, num2)).toBe((num1 & num2) === num2 ? true : false)
-    expect(type.numberMatch(num1, num2, "True", "False")).toBe((num1 & num2) === num2 ? "True" : "False")
-  }
-
-  // Number Set, Unset, Toggle and Get Bit
-  expect(type.numberSetBit(0, 5)).toBe(0b10000)
-  expect(type.numberUnsetBit(0b1111, 3)).toBe(0b1011)
-  expect(type.numberToggleBit(0b1010, 3)).toBe(0b1110)
-  expect(type.numberBit(0b1100, 2)).toBe(0)
-
-  // Get High / Low Bits Num 
-  expect(type.numberHighBitsNum(0xFF).unwrap()).toBe(8)
-  expect(type.numberHighBitsNum(0xAA).unwrap()).toBe(4)
-  expect(type.numberLowBitsNum(0xFF, 8).unwrap()).toBe(0)
-  expect(type.numberLowBitsNum(0xAA, 8).unwrap()).toBe(4)
-})
diff --git a/server/common.ts b/server/common.ts
deleted file mode 100644
index f8b5d9d..0000000
--- a/server/common.ts
+++ /dev/null
@@ -1,191 +0,0 @@
-import _ from "lodash"
-import { Option, Some, None, Result, Ok, Err } from "ts-results-es";
-import { z } from "zod";
-
-export function UNUSED(_: unknown): void { }
-
-export namespace type {
-
-  const NUMBER_MAX_LENGTH = 32
-
-
-  export const ErrorTypeSchema = z.union([
-    z.literal("Not Integer"),
-    z.literal("Not Unsigned Integer"),
-    z.literal("Not 32Bits Integer")
-  ])
-
-  export type ErrorType = z.infer<typeof ErrorTypeSchema>
-
-  export const Integer = z.number().int()
-  export const UInteger = z.number().int().nonnegative()
-
-  export const UInt8 = UInteger.lt(Math.pow(2, 8))
-  export const UInt16 = UInteger.lt(Math.pow(2, 16))
-  export const UInt32 = UInteger.lt(Math.pow(2, 32))
-
-  export const Int8 = Integer.lt(Math.pow(2, 7)).gte(-Math.pow(2, 8))
-  export const Int16 = Integer.lt(Math.pow(2, 15)).gte(-Math.pow(2, 16))
-  export const Int32 = Integer.lt(Math.pow(2, 31)).gte(-Math.pow(2, 32))
-
-  export function numberToBytes(num: number, bytesLength: number, isRightHigh: boolean = false)
-    : Result<Uint8Array, ErrorType> {
-    // Check Integer
-    if (!Int32.safeParse(num).success && !UInt32.lte(32).safeParse(bytesLength).success) {
-      console.error(`Number : ${num}, 2 ^ 31 = ${2 ^ 31}`)
-      console.error(Int32.safeParse(num).error?.message)
-      return new Err("Not 32Bits Integer")
-    }
-
-    var array = new Uint8Array(bytesLength)
-
-    if (isRightHigh) {
-      for (let i = 0; i < bytesLength; i++) {
-        array[bytesLength - 1 - i] = ((num >> (i << 3)) & 0xFF)
-      }
-    } else {
-      for (let i = 0; i < bytesLength; i++) {
-        array[i] = ((num >> (i << 3)) & 0xFF)
-      }
-    }
-
-    return new Ok(array)
-  }
-
-  export function bytesToNumber(bytes: Uint8Array, isRightHigh: boolean = false): number {
-    let num = 0
-    const len = bytes.length
-    if (isRightHigh) {
-      for (let i = 0; i < len; i++) {
-        num += bytes[len - 1 - i] << (i << 3)
-      }
-    } else {
-      for (let i = 0; i < len; i++) {
-        num += bytes[i] << (i << 3)
-      }
-    }
-    return num
-  }
-
-
-  export function numberMatch(
-    srcNum: number,
-    destNum: number
-  ): boolean;
-
-  export function numberMatch<T>(
-    srcNum: number,
-    destNum: number,
-    True: T,
-    False: T
-  ): T;
-
-  export function numberMatch<T>(
-    srcNum: number,
-    destNum: number,
-    True: T = true as T,
-    False: T = false as T
-  ): T {
-    const ret = (srcNum & destNum) === destNum;
-    return ret ? True : False;
-  }
-
-  export function numberMatchEnum() {
-
-  }
-
-  export function numberSetBit(num: number, loc: number): number {
-    return num | (1 << (loc - 1))
-  }
-
-  export function numberUnsetBit(num: number, loc: number): number {
-    return num & ~(1 << (loc - 1))
-  }
-
-  export function numberToggleBit(num: number, loc: number): number {
-    return num ^ (1 << (loc - 1))
-  }
-
-  export function numberBit(num: number, loc: number): number {
-    return (num >> (loc - 1)) & 1
-  }
-
-  export function numberHighBitsNum(num: number, maxLen: number = NUMBER_MAX_LENGTH): Result<number, ErrorType> {
-    if (!Int32.safeParse(num).success && maxLen > 32) {
-      return new Err("Not 32Bits Integer")
-    }
-
-    let cnt = 0
-    for (let i = 0; i < maxLen; i++) {
-      if (num & (1 << i)) {
-        cnt++
-      }
-    }
-    return new Ok(cnt)
-  }
-
-  export function numberLowBitsNum(num: number, maxLen: number): Result<number, ErrorType> {
-    if (!Int32.safeParse(num).success && maxLen > 32) {
-      return new Err("Not 32Bits Integer")
-    }
-
-    let cnt = 0
-    for (let i = 0; i < maxLen; i++) {
-      if (!(num & (1 << i))) {
-        cnt++
-      }
-    }
-    return new Ok(cnt)
-  }
-
-  export function isStringArray(obj: any): obj is Array<string> {
-    return z.string().array().safeParse(obj).success
-  }
-
-  export function isNumberArray(obj: any): obj is Array<number> {
-    return z.number().array().safeParse(obj).success
-  }
-}
-
-export namespace fun {
-
-  export function randomFromArray(array: Array<any>) {
-    return array[_.random(0, array.length - 1, false)]
-  }
-
-  export function sqlConditionFromArray(
-    columnName: string,
-    array: Array<string>,
-    type: "AND" | "OR"
-  ): Option<string> {
-    let condition: string = ""
-    const len = array.length
-    if (len == 0) {
-      return None
-    }
-    for (let i = 0; i < len; i++) {
-      condition.concat(`${columnName}=${array[i]}`)
-      if (i != len - 1) {
-        condition.concat(` ${type} `)
-      }
-    }
-
-    return new Some(condition)
-  }
-
-  export function sqlConditionFromString(
-    columnName: string,
-    str: string,
-    type: "AND" | "OR",
-    delimiter: string = " "
-  ): Option<string> {
-    if (str.length == 0) {
-      return None
-    }
-
-    const array = str.split(delimiter)
-    return sqlConditionFromArray(columnName, array, type)
-  }
-}
-
-
diff --git a/server/database.test.ts b/server/database.test.ts
deleted file mode 100644
index 1e85dc1..0000000
--- a/server/database.test.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { test, expect } from "bun:test"
-import * as db from "./database.ts"
-import _, { rearg } from "lodash"
-import { None, Ok, Option, Some } from "ts-results-es"
-
-// Test basic function for database
-test("DataBase", () => {
-  const allTables = db.allTables()
-  expect(allTables).toBeArray()
-  expect(allTables).toEqual(["Users", "Boards"])
-  expect(db.BoardTable.countAll()).toBe(0)
-  expect(db.UserTable.countAll()).toBe(0)
-})
-
-// Test Boards table function
-const boardsNumber = 10
-const rooms = ["A1", "A1", "A1", "A1", "A1", "A2", "A2", "A2", "A2", "A2"]
-test("Find something empty", () => {
-  const findEmptyByID = db.BoardTable.find(_.random(0, boardsNumber))
-  expect(findEmptyByID).toEqual(Ok(None))
-  const findEmptyByName = db.BoardTable.find("Hello", "World")
-  expect(findEmptyByName).toEqual(Ok(None))
-})
-
-test("Add some boards", () => {
-  const boardsArray: Array<db.Board> = []
-  for (let i = 0; i < boardsNumber; i++) {
-    boardsArray.push({
-      id: i,
-      name: `Board ${i}`,
-      room: rooms[i],
-      ipv4: `192.168.172.${i}`,
-      port: i,
-    })
-  }
-  const retAdd = db.BoardTable.addFromArray(boardsArray)
-  const isAddOk = retAdd.isOk()
-  expect(isAddOk).toBeTrue()
-})
-
-test("Get boards table column unique element", () => {
-  expect(db.BoardTable.rooms().unwrap()).toEqual(["A1", "A2"])
-})
-
-test("Find something from boards table", () => {
-  expect(db.BoardTable.find(1)).toEqual(Ok(Some({
-    id: 1,
-    name: `Board ${1}`,
-    room: rooms[1],
-    ipv4: `192.168.172.${1}`,
-    port: 1,
-  } as db.Board)))
-  expect(db.BoardTable.find("Board 3", "A1")).toEqual(Ok(Some({
-    id: 3,
-    name: `Board ${3}`,
-    room: rooms[3],
-    ipv4: `192.168.172.${3}`,
-    port: 3,
-  } as db.Board)))
-})
-
-test("Get count of elements from boards table", () => {
-  expect(db.BoardTable.countByName("Board 1")).toBe(1)
-  expect(db.BoardTable.countByRoom("A1")).toBe(5)
-})
diff --git a/server/database.ts b/server/database.ts
deleted file mode 100644
index 8bc507e..0000000
--- a/server/database.ts
+++ /dev/null
@@ -1,478 +0,0 @@
-import { Database, type Changes } from "bun:sqlite";
-import _ from "lodash";
-import { Ok, Err, Result, None, Some, Option } from "ts-results-es";
-import { z } from "zod";
-import { fun, type } from "./common";
-
-const db = new Database("lab.sqlite", { strict: true })
-initDB(db);
-
-// Error Type
-const BoardErrorTypeSchema = z.union([
-  z.literal("Wrong Type"),
-  z.literal("No Such Board(s)"),
-  z.literal("ID Conflict"),
-  z.literal("Name Conflict")
-])
-
-export type BoardErrorType = z.infer<typeof BoardErrorTypeSchema>
-
-const boardSchema = z.object({
-  id: z.number().nonnegative(),
-  name: z.string(),
-  room: z.string(),
-  ipv4: z.string().ip({ version: "v4" }),
-  ipv6: z.string().ip({ version: "v6" }),
-  port: z.number().nonnegative().lte(65535),
-  cmdID: z.number().nonnegative()
-}).partial({
-  ipv6: true,
-  cmdID: true
-})
-
-export type Board = z.infer<typeof boardSchema>
-export type BoardColumn = keyof Board
-
-export function isBoard(obj: any): obj is Board {
-  return boardSchema.safeParse(obj).success
-}
-
-export function isBoardArray(obj: any): obj is Array<Board> {
-  return boardSchema.array().safeParse(obj).success
-}
-
-export function isBoardColumn(obj: any): obj is BoardColumn {
-  return boardSchema.keyof().safeParse(obj).success
-}
-
-const userSchema = z.object({
-  id: z.number().nonnegative(),
-  name: z.string(),
-  password: z.string(),
-  boardID: z.number(),
-}).partial({
-  boardID: true,
-})
-
-export type User = z.infer<typeof userSchema>
-export type UserColumn = keyof User
-
-export function isUser(obj: any): obj is User {
-  return userSchema.safeParse(obj).success
-}
-
-export function isUserArray(obj: any): obj is Array<User> {
-  return userSchema.array().safeParse(obj).success
-}
-
-export function isUserColumn(obj: any): obj is UserColumn {
-  return userSchema.keyof().safeParse(obj).success
-}
-
-function initDB(db: Database) {
-  const tables = allTables()
-
-  if (!tables.includes("Users")) {
-    db.query(`
-      CREATE TABLE Users(
-        id         INT PRIMARY KEY   NOT NULL,
-        name       TEXT              NOT NULL,
-        password   TEXT              NOT NULL
-      );
-    `).run();
-  }
-
-  if (!tables.includes("Boards"))
-    db.query(`
-      CREATE TABLE Boards(
-        id         INT PRIMARY KEY   NOT NULL,
-        name       TEXT              NOT NULL,
-        room       TEXT              NOT NULL,
-        ipv4       CHAR(16)          NOT NULL,
-        ipv6       CHAR(46)                  ,
-        port       INT               NOT NULL
-      )
-    `).run();
-}
-
-export function allTables(): Array<string> {
-  const query = db.query(`SELECT name FROM sqlite_master WHERE type='table'`)
-  var tables = new Array()
-  // Flaten array
-  for (const item of query.values()) {
-    tables.push(item[0])
-  }
-
-  query.finalize()
-  return tables
-}
-
-export function tableColumnName(table: string): Array<string> {
-  const query = db.query(`PRAGMA table_info(${table})`)
-
-  var columnName = new Array()
-  for (const column of query.values()) {
-    columnName.push(column[1])
-  }
-
-  return columnName
-}
-
-export namespace BoardTable {
-
-  export function add(board: Board): Result<Changes, BoardErrorType> {
-    if (!isBoard(board)) {
-      return new Err("Wrong Type")
-    }
-
-    // Ensure no id conflict
-    if (board.id == 0) {
-      const cnt = countAll()
-      board.id = cnt + 1
-    } else {
-      const retID = includes(board.id)
-      if (retID.isOk()) {
-        if (retID.value) return new Err("ID Conflict")
-      } else {
-        return new Err("Wrong Type")
-      }
-    }
-
-    // Ensure no name conflict in the same room
-    {
-      const retName = includes(board.name, board.room)
-      if (retName.isOk()) {
-        if (retName.value) {
-          return new Err("Name Conflict")
-        }
-      } else {
-        return new Err("Wrong Type")
-      }
-    }
-
-    const query = db.query(`
-    INSERT INTO Boards VALUES 
-    (${board.id},
-    '${board.name}',
-    '${board.room}',
-    '${board.ipv4}',
-    '${_.isUndefined(board.ipv6) ? "NULL" : board.ipv6}',
-    ${board.port});
-  `)
-
-    return Ok(query.run())
-  }
-
-  export function addFromArray(array: Array<Board>)
-    : Result<Array<Changes>, BoardErrorType> {
-
-    let arrayChanges: Array<Changes> = []
-    for (const item of array) {
-      const ret = add(item)
-      if (ret.isErr()) {
-        return ret
-      } else {
-        arrayChanges.push(ret.value)
-      }
-    }
-
-    return new Ok(arrayChanges)
-  }
-
-  export function all(): Option<Array<Board>> {
-    const query = db.query(`SELECT * FROM Boards`)
-    const ret = query.all()
-    query.finalize()
-
-    if (isBoardArray(ret)) {
-      return Some(ret)
-    } else {
-      return None
-    }
-  }
-
-  export function countAll(): number {
-    const query = db.query(`SELECT COUNT(*) FROM Boards`)
-    return query.values()[0][0] as number
-  }
-
-  export function countByName(name: string): number {
-    const query = db.query(`SELECT * FROM Boards WHERE name=${name}`)
-    return query.values()[0][0] as number
-  }
-
-  export function countByRoom(room: string): number {
-    const query = db.query(`SELECT * FROM Boards WHERE room=${room}`)
-    return query.values()[0][0] as number
-  }
-
-  export function remove(name: string, room: string): Result<Board, BoardErrorType>
-  export function remove(id: number): Result<Board, BoardErrorType>
-  export function remove(board: Board): Result<Board, BoardErrorType>
-  export function remove(arg1: any, arg2?: any): Result<Board, BoardErrorType> {
-    let retBoard
-    let condition: string
-    if (isBoard(arg1)) {
-      retBoard = _.cloneDeep(arg1)
-      condition = `id=${arg1.id}`
-
-    } else if (_.isNumber(arg1)) {
-      retBoard = find(arg1)
-      if (retBoard.isOk() && retBoard.value.isSome()) {
-        retBoard = _.cloneDeep(retBoard.value.value)
-        condition = `id=${arg1}`
-      } else {
-        return new Err("Wrong Type")
-      }
-
-    } else if (_.isString(arg1) && _.isString(arg2)) {
-      retBoard = find(arg1, arg2)
-      if (retBoard.isOk() && retBoard.value.isSome()) {
-        retBoard = _.cloneDeep(retBoard.value.value)
-        condition = `name=${arg1}`
-      } else {
-        return new Err("No Such Board(s)")
-      }
-
-    } else {
-      return new Err("Wrong Type")
-    }
-
-    const query = db.query(`DELETE FROM Boards WHERE ${condition}`)
-    query.run()
-
-    return new Ok(retBoard)
-  }
-
-  export function removeAll(): Option<Array<Board>> {
-    const array = all()
-    const query = db.query(`DELETE FROM Boards`)
-    query.run()
-
-
-    if (array.isSome()) {
-      return new Some(array.value)
-    } else {
-      return None
-    }
-  }
-
-  export function removeByCondition(condition: string): Result<Array<Board>, BoardErrorType> {
-    const rsArr = findByCondition(condition)
-    if (rsArr.isNone()) {
-      return new Err("No Such Board(s)")
-    }
-
-    const query = db.query(`DELETE FROM Boards WHERE ${condition}`)
-    query.run()
-
-    return new Ok(rsArr.value)
-  }
-
-  export function removeByValue(columnName: string, val: string | Array<string>)
-    : Result<Array<Board>, BoardErrorType> {
-
-    if (!isBoardColumn(columnName)) {
-      return new Err("Wrong Type")
-    }
-
-    let condition: string
-    if (_.isString(val)) {
-      const retCond = fun.sqlConditionFromString(columnName, val, "OR")
-      if (retCond.isSome()) {
-        condition = retCond.value
-      } else {
-        return new Err("Wrong Type")
-      }
-    } else if (type.isStringArray(val)) {
-      const retCond = fun.sqlConditionFromArray(columnName, val, "OR")
-      if (retCond.isSome()) {
-        condition = retCond.value
-      } else {
-        return new Err("Wrong Type")
-      }
-    } else {
-      return new Err("Wrong Type")
-    }
-
-    return removeByCondition(condition)
-  }
-
-  export function removeByName(name: string | Array<string>)
-    : Result<Array<Board>, BoardErrorType> {
-    return removeByValue("name", name)
-  }
-
-  export function removeByRoom(room: string | Array<string>)
-    : Result<Array<Board>, BoardErrorType> {
-
-    return removeByValue("room", room)
-  }
-
-  export function rooms(): Option<Array<string>> {
-    const query = db.query(`SELECT DISTINCT room FROM Boards`)
-    let rooms: Array<string> = []
-    const retVal = query.values()
-
-    if (retVal.length > 0) {
-      for (const item of retVal) {
-        rooms.push(item[0] as string)
-      }
-      return new Some(rooms)
-    } else {
-      return None
-    }
-  }
-
-
-  export function find(name: string, room: string): Result<Option<Board>, BoardErrorType>
-  export function find(id: number): Result<Option<Board>, BoardErrorType>
-  export function find(arg1: any, arg2?: any): Result<Option<Board>, BoardErrorType> {
-    let condition: string
-    if (_.isNumber(arg1)) {
-      condition = `id=${arg1}`
-
-    } else if (_.isString(arg1) && _.isString(arg2)) {
-      condition = `name='${arg1}' AND room='${arg2}'`
-
-    } else {
-      return new Err("Wrong Type")
-    }
-
-    const query = db.query(`SELECT * FROM Boards WHERE ${condition}`)
-
-    const spRet = boardSchema.safeParse(query.get())
-
-    if (spRet.success) {
-      return new Ok(Some(spRet.data))
-    } else {
-      return new Ok(None)
-    }
-  }
-
-  export function findByName(name: string | Array<string>): Result<Option<Array<Board>>, BoardErrorType> {
-    let condition: string
-    if (_.isString(name)) {
-      const retCond = fun.sqlConditionFromString("name", name, "OR")
-      if (retCond.isSome()) {
-        condition = retCond.value
-      } else {
-        return new Err("Wrong Type")
-      }
-    } else if (type.isStringArray(name)) {
-      const retCond = fun.sqlConditionFromArray("name", name, "OR")
-      if (retCond.isSome()) {
-        condition = retCond.value
-      } else {
-        return new Err("Wrong Type")
-      }
-    } else {
-      return new Err("Wrong Type")
-    }
-
-    return new Ok(findByCondition(condition))
-  }
-
-  export function findByCondition(condition: string): Option<Array<Board>> {
-    const query = db.query(`SELECT * FROM Boards WHERE ${condition}`)
-    const ret = query.all()
-    if (isBoardArray(ret)) {
-      return new Some(ret)
-    } else {
-      return None
-    }
-  }
-
-  export function findByValue(columnName: string, val: string | Array<string>)
-    : Result<Option<Array<Board>>, BoardErrorType> {
-
-    if (!isBoardColumn(columnName)) {
-      return new Err("Wrong Type")
-    }
-
-    let condition: string
-    if (_.isString(val)) {
-      const retCond = fun.sqlConditionFromString(columnName, val, "OR")
-      if (retCond.isSome()) {
-        condition = retCond.value
-      } else {
-        return new Err("Wrong Type")
-      }
-    } else if (type.isStringArray(val)) {
-      const retCond = fun.sqlConditionFromArray(columnName, val, "OR")
-      if (retCond.isSome()) {
-        condition = retCond.value
-      } else {
-        return new Err("Wrong Type")
-      }
-    } else {
-      return new Err("Wrong Type")
-    }
-
-    return new Ok(findByCondition(condition))
-  }
-
-  export function includes(name: string, room?: string): Result<boolean, BoardErrorType>
-  export function includes(id: number): Result<boolean, BoardErrorType>
-  export function includes(arg1: any, arg2?: any): Result<boolean, BoardErrorType> {
-    let condition: string
-    if (_.isUndefined(arg2)) {
-      if (_.isNumber(arg1)) {
-        condition = `id=${arg1}`
-
-      } else if (_.isString(arg1)) {
-        condition = `name='${arg1}'`
-
-      } else {
-        return new Err("Wrong Type")
-      }
-    } else {
-      if (_.isString(arg1) && _.isString(arg2)) {
-        condition = `name='${arg1} AND room=${arg2}'`
-      } else {
-        return new Err("Wrong Type")
-      }
-    }
-
-    const query = db.query(`SELECT COUNT(*) FROM Boards WHERE ${condition}`)
-    const num = query.values()[0][0] as number
-
-    return new Ok(num > 0 ? true : false)
-  }
-
-}
-
-export namespace UserTable {
-
-  export function countAll(): number {
-    const query = db.query(`SELECT COUNT(*) FROM Users`)
-    return query.values()[0][0] as number
-  }
-
-
-  export function find(id: number): Result<Option<User>, "Wrong Type">
-  export function find(name: string): Result<Option<User>, "Wrong Type">
-  export function find(arg: any): Result<Option<User>, "Wrong Type"> {
-    let condition: string
-    if (_.isNumber(arg)) {
-      condition = `id=${arg}`
-    } else if (_.isString(arg)) {
-      condition = `name=${arg}`
-    } else {
-      return new Err("Wrong Type")
-    }
-
-    const query = db.query(`SELECT * FROM Users WHERE name='${arg}'`)
-
-    const spRet = userSchema.safeParse(query.get())
-
-    if (spRet.success) {
-      return new Ok(Some(spRet.data))
-    } else {
-      return new Ok(None)
-    }
-  }
-
-}
-
-
diff --git a/server/index.ts b/server/index.ts
deleted file mode 100644
index 1de8dd6..0000000
--- a/server/index.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { createBunServeHandler } from "trpc-bun-adapter";
-import { appRouter } from "./router.ts"
-
-Bun.serve(createBunServeHandler({
-  router: appRouter,
-  responseMeta() {
-    return {
-      status: 200,
-      headers: {
-        "Access-Control-Allow-Origin": "*",
-        "Access-Control-Allow-Methods": "GET, PUT, POST, OPTIONS",
-        "Access-Control-Allow-Headers": "Content-Type, Authorization"
-      }
-    }
-  }
-}, {
-  port: 3002,
-  fetch() {
-    return Response.json({ message: "Not Found" }, { status: 404 });
-  }
-}))
diff --git a/server/msgBus.ts b/server/msgBus.ts
deleted file mode 100644
index c413269..0000000
--- a/server/msgBus.ts
+++ /dev/null
@@ -1 +0,0 @@
-import { MsgProtocol } from "./msgProtocol";
diff --git a/server/msgProtocol.ts b/server/msgProtocol.ts
deleted file mode 100644
index 5c8fdab..0000000
--- a/server/msgProtocol.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-import { type TransferListItem } from "worker_threads";
-import { z } from "zod";
-import { UNUSED } from "./common";
-
-export namespace MsgProtocol {
-  const QueryDataSchema = z.object({ type: z.literal("Query"), args: z.any() })
-  const ResultDataSchema = z.object({ type: z.literal("Result"), result: z.any() })
-  const ErrorDataSchema = z.object({ type: z.literal("Error"), error: z.string() })
-
-  const MessageSchema = z.object({
-    command: z.string(),
-    data: z.discriminatedUnion("type", [QueryDataSchema, ResultDataSchema, ErrorDataSchema]),
-    dest: z.string(),
-    src: z.string(),
-  })
-  const MessageQuerySchema = z.object({
-    command: z.string(),
-    data: QueryDataSchema,
-    dest: z.string(),
-    src: z.string(),
-  })
-  const MessageResultSchema = z.object({
-    command: z.string(),
-    data: ResultDataSchema,
-    dest: z.string(),
-    src: z.string(),
-  })
-  const MessageErrorSchema = z.object({
-    command: z.string(),
-    data: ErrorDataSchema,
-    dest: z.string(),
-    src: z.string(),
-  })
-  const MessageHandlerSchema = z.function()
-    .args(z.union([MessageResultSchema, MessageErrorSchema]))
-    .returns(z.void())
-
-  export type Message = z.infer<typeof MessageSchema>
-  export type MessageQuery = z.infer<typeof MessageQuerySchema>
-  export type MessageResult = z.infer<typeof MessageResultSchema>
-  export type MessageError = z.infer<typeof MessageErrorSchema>
-  export type MessageHandler = z.infer<typeof MessageHandlerSchema>
-
-  export function isMessage(obj: any): obj is Message {
-    return MessageSchema.safeParse(obj).success
-  }
-  export function isMessageQuery(obj: any): obj is MessageQuery {
-    return MessageQuerySchema.safeParse(obj).success
-  }
-  export function isMessageResult(obj: any): obj is MessageResult {
-    return MessageResultSchema.safeParse(obj).success
-  }
-  export function isMessageError(obj: any): obj is MessageError {
-    return MessageErrorSchema.safeParse(obj).success
-  }
-
-  export function genMessageResult(result: any, srcMsg: MessageQuery): MessageResult {
-    return {
-      command: srcMsg.command,
-      dest: srcMsg.src,
-      src: srcMsg.dest,
-      data: {
-        type: "Result",
-        result: result
-      }
-    } as MessageResult
-  }
-  export function genMessageError(error: string, srcMsg: MessageQuery): MessageError {
-    return {
-      command: srcMsg.command,
-      dest: srcMsg.src,
-      src: srcMsg.dest,
-      data: {
-        type: "Error",
-        error: error
-      }
-    } as MessageError
-  }
-}
diff --git a/server/router.ts b/server/router.ts
deleted file mode 100644
index 19690b6..0000000
--- a/server/router.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { router, publicProcedure } from "./trpc.ts"
-
-export const appRouter = router({
-  api: router({
-    status: publicProcedure.query(() => "OK"),
-    signUp: publicProcedure.query((opts) => {
-
-    })
-  })
-});
-
-export type AppRouter = typeof appRouter;
diff --git a/server/trpc.ts b/server/trpc.ts
deleted file mode 100644
index 0db673e..0000000
--- a/server/trpc.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { initTRPC } from '@trpc/server';
-
-const t = initTRPC.create();
-
-export const router = t.router;
-export const publicProcedure = t.procedure;
diff --git a/server/udp.test.ts b/server/udp.test.ts
deleted file mode 100644
index 690b7d0..0000000
--- a/server/udp.test.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { expect, test } from "bun:test"
-import { udpServer, udpClient } from "./udp"
-
-const udpServerAddr = "127.0.0.1"
-const udpServerPort = await udpServer.port()
-
-console.info("Ready to Test UDP")
-
-test("Test Send String", async () => {
-  const str = "Hello My Server"
-  const retSend = await udpClient.sendString(str, udpServerPort, udpServerAddr)
-  expect(retSend).toBe(true)
-
-  const retReceive = await udpServer.lastestData(udpServerAddr)
-  if (retReceive.isSome()) {
-    const data = retReceive.value
-    expect(data.body).toBe(str)
-    expect(data.address).toBe(udpServerAddr)
-  } else {
-    expect().fail("Not Receive Anything")
-  }
-})
diff --git a/server/udp.ts b/server/udp.ts
deleted file mode 100644
index 7c1fc81..0000000
--- a/server/udp.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-import { resolve } from "path";
-import Tinypool from "tinypool";
-import type { UDPReceiveProcotol, UDPSendProtocol } from "./udpProtocol";
-import type { udp } from "bun";
-import { Option } from "ts-results-es";
-
-const SERVER_PATH = resolve(__dirname, "./udpServer.ts")
-const CLIENT_PATH = resolve(__dirname, "./udpClient.ts")
-
-export type UDPBodyType = (
-  udp.Data |
-  UDPSendProtocol.CmdPackage |
-  UDPSendProtocol.DataPackage |
-  UDPReceiveProcotol.ReadPackage |
-  UDPReceiveProcotol.WritePackage
-)
-
-type UDPDataType<T extends UDPBodyType = UDPBodyType> = {
-  address: string,
-  body: T,
-  port: number,
-  date?: string,
-}
-
-
-const udpClientsPool = new Tinypool({
-  filename: CLIENT_PATH,
-  workerData: {}
-})
-
-const udpServerPool = new Tinypool({
-  filename: SERVER_PATH,
-  workerData: {},
-  maxThreads: 1,
-  minThreads: 1,
-})
-
-export namespace udpServer {
-
-  export async function port(): Promise<number> {
-    return udpServerPool.run(null, { name: "port" })
-  }
-
-  export async function lastestData(address: string): Promise<Option<UDPDataType<udp.Data>>> {
-    return udpServerPool.run(address, { name: "lastestData" })
-  }
-
-  export async function oldestData(address: string): Promise<Option<UDPDataType<udp.Data>>> {
-    return udpServerPool.run(address, { name: "oldestData" })
-  }
-
-}
-
-export namespace udpClient {
-
-  export async function sendString(data: string, port: number, address: string): Promise<boolean> {
-    return udpClientsPool.run({
-      body: data,
-      port: port,
-      address: address
-    } as UDPDataType<string>, { name: "sendString" })
-  }
-
-  export async function sendUint8Array(data: Uint8Array, port: number, address: string): Promise<boolean> {
-    return udpClientsPool.run({
-      body: data,
-      port: port,
-      address: address
-    } as UDPDataType<Uint8Array>, { name: "sendUint8Array" })
-  }
-
-  export async function sendBunData(data: udp.Data, port: number, address: string): Promise<boolean> {
-    return udpClientsPool.run({
-      body: data,
-      port: port,
-      address: address
-    } as UDPDataType<udp.Data>, { name: "sendUint8Array" })
-  }
-}
-export type { UDPDataType }
diff --git a/server/udpClient.ts b/server/udpClient.ts
deleted file mode 100644
index c59ff76..0000000
--- a/server/udpClient.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import type { udp } from "bun"
-import type { UDPDataType } from "./udp"
-
-const udpClient = await Bun.udpSocket({})
-
-export function sendString(data: UDPDataType<string>): boolean {
-  return udpClient.send(data.body, data.port, data.address)
-}
-
-export function sendUint8Array(data: UDPDataType<Uint8Array>): boolean {
-  return udpClient.send(data.body, data.port, data.address)
-}
-
-export function sendBunData(data: UDPDataType<udp.Data>): boolean {
-  return udpClient.send(data.body, data.port, data.address)
-}
-
diff --git a/server/udpProtocol.ts b/server/udpProtocol.ts
deleted file mode 100644
index 3198958..0000000
--- a/server/udpProtocol.ts
+++ /dev/null
@@ -1,201 +0,0 @@
-import { type } from "./common";
-import { z } from "zod";
-import _ from "lodash";
-import { Err, Ok, type Result } from "ts-results-es";
-import { isUint8Array } from "util/types";
-
-const PKG_SIGN_ADDR = 0x00
-const PKG_SIGN_DATA = 0xFF
-const PKG_SIGN_READ = 0x0F
-const PKG_SIGN_WRITE = 0xF0
-
-export namespace UDPSendProtocol {
-
-  const CMDLOC_BURST_TYPE = 5
-  const CMDLOC_TASK_ID = 3
-  const CMDLOC_READ_WRITE_TYPE = 0
-
-  const CmdPackageOptionsSchema = z.object({
-    burstType: z.enum(["Fixed", "Extend"]),
-    taskID: z.number().nonnegative().lt(4),
-    readWriteType: z.enum(["r", "w"])
-  })
-
-  export type CmdPackageOptions = z.infer<typeof CmdPackageOptionsSchema>
-
-  export function isCmdPackageOptions(obj: any): obj is CmdPackageOptions {
-    return CmdPackageOptionsSchema.safeParse(obj).success
-  }
-
-  export class CmdPackage {
-    private ID: number = PKG_SIGN_ADDR
-    private commandType: number = 0
-    private burstLength: number = 0
-    private _reserved: number = 0
-    private address: number = 0
-
-
-    constructor(array: Uint8Array)
-    constructor(options: CmdPackageOptions)
-    constructor(arg: any) {
-      if (isCmdPackageOptions(arg)) {
-        this.setCommandType(arg)
-      } else if (isUint8Array(arg)) {
-        this.ID = arg[0]
-        this.commandType = arg[1]
-        this.burstLength = arg[2]
-        this._reserved = arg[3]
-        this.address = type.bytesToNumber(arg.slice(4))
-      } else {
-        throw new Err("Wrong Type")
-      }
-    }
-
-    setCommandType(options: CmdPackageOptions) {
-      const validOptions = CmdPackageOptionsSchema.parse(options)
-      this.commandType = (
-        ((validOptions.burstType === "Fixed") ? 1 << CMDLOC_BURST_TYPE : 0) |
-        (validOptions.taskID << CMDLOC_TASK_ID) |
-        ((validOptions.readWriteType === "r") ? 1 << CMDLOC_READ_WRITE_TYPE : 0)
-      )
-    }
-
-    setBurstLength(len: number): Result<null, "Not 8Bits Unsigned Integer"> {
-      if (!type.UInt8.safeParse(len).success) {
-        return new Err("Not 8Bits Unsigned Integer")
-      }
-      this.burstLength = len
-      return new Ok(null)
-    }
-
-    setAddress(addr: number): Result<null, "Not 32Bits Unsigned Integer"> {
-      if (!type.UInt32.safeParse(addr).success) {
-        return new Err("Not 32Bits Unsigned Integer")
-      }
-      this.address = addr
-      return new Ok(null)
-    }
-
-    options(): CmdPackageOptions {
-      return {
-        burstType: type.numberMatch(this.commandType, CMDLOC_BURST_TYPE, "Extend", "Fixed"),
-        taskID: (this.commandType >> CMDLOC_TASK_ID) & 0b0011,
-        readWriteType: type.numberMatch(this.commandType, CMDLOC_READ_WRITE_TYPE, "w", "r")
-      }
-    }
-
-    toUint8Array(): Uint8Array {
-      var array = new Uint8Array(8)
-
-      array[0] = this.ID
-      array[1] = this.commandType
-      array[2] = this.burstLength
-      array[3] = this._reserved
-
-      // Already check address length at the begining of set address
-      let addressBytes = type.numberToBytes(this.address, 4).unwrap()
-      array.set(addressBytes, 4)
-
-      return array
-    }
-  }
-
-  export function isCmdPackage(obj: any): obj is CmdPackage {
-    return obj instanceof CmdPackage
-  }
-
-  export class DataPackage {
-    private ID: number = PKG_SIGN_DATA
-    private _reserved: number = 0
-    private body: Uint8Array
-
-    constructor(body: Uint8Array) {
-      this.body = body
-    }
-
-    toUint8Array(): Uint8Array {
-      var array = new Uint8Array(4 + this.body.length)
-
-      array[0] = this.ID
-      array.fill(this._reserved, 1, 4)
-      array.set(this.body, 4)
-
-      return array
-    }
-  }
-
-  export function isDataPackage(obj: any): obj is DataPackage {
-    return obj instanceof DataPackage
-  }
-
-}
-
-export namespace UDPReceiveProcotol {
-
-  export class ReadPackage {
-    private ID: number = PKG_SIGN_READ
-    private taskID: number = 0
-    private resp: number = 0
-    private _reserved: number = 0
-    body: Uint8Array
-
-    constructor(array: Uint8Array) {
-      if (array.length < 5) {
-        throw new Err("Not Long Enough")
-      }
-      this.ID = array[0]
-      this.taskID = array[1]
-      this.resp = array[2]
-      this._reserved = array[3]
-      this.body = new Uint8Array(array.slice(4))
-    }
-
-    toUint8Array(): Uint8Array {
-      let array = new Uint8Array(4 + this.body.length)
-
-      array[0] = this.ID
-      array[1] = this.taskID
-      array[2] = this.resp
-      array[3] = this._reserved
-      array.set(this.body, 4)
-
-      return array
-    }
-  }
-
-  export function isReadPackage(obj: any): obj is ReadPackage {
-    return obj instanceof ReadPackage
-  }
-
-  export class WritePackage {
-    private ID: number = PKG_SIGN_WRITE
-    private taskID: number = 0
-    private resp: number = 0
-    private _reserved: number = 0
-
-
-    constructor(array: Uint8Array) {
-      if (array.length < 4) {
-        throw new Err("Not Long Enough")
-      }
-      this.ID = array[0]
-      this.taskID = array[1]
-      this.resp = array[2]
-      this._reserved = array[3]
-    }
-
-    toUint8Array(): Uint8Array {
-      return new Uint8Array([
-        this.ID,
-        this.taskID,
-        this.resp,
-        this._reserved
-      ])
-    }
-  }
-
-  export function isWritePackage(obj: any): obj is WritePackage {
-    return obj instanceof WritePackage
-  }
-
-}
diff --git a/server/udpServer.ts b/server/udpServer.ts
deleted file mode 100644
index d9fe296..0000000
--- a/server/udpServer.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-import _ from "lodash"
-import { type udp } from "bun"
-import type { UDPDataType } from "./udp";
-import { None, Some, type Option } from "ts-results-es";
-import { z } from "zod";
-
-// Bun Data Type
-interface BinaryTypeList {
-  arraybuffer: ArrayBuffer;
-  buffer: Buffer;
-  uint8array: Uint8Array;
-}
-type BinaryType = keyof BinaryTypeList;
-
-const receivedData: Map<string, Array<{
-  body: udp.Data,
-  port: number,
-  date: string
-}>> = new Map()
-
-const udpServer = await Bun.udpSocket({
-  port: 33000,
-  socket: {
-    data(
-      _socket: udp.Socket<BinaryType>,
-      data: BinaryTypeList[BinaryType],
-      port: number,
-      address: string,
-    ) {
-      // Add Received Data
-      let arrayData = receivedData.get(address)
-      if (_.isUndefined(arrayData)) {
-
-      } else {
-        receivedData.set(address, [])
-        arrayData.push({
-          body: data,
-          port: port,
-          date: new Date().toUTCString()
-        })
-      }
-    }
-  }
-})
-
-function port(): number {
-  return udpServer.port
-}
-
-function lastestData(address: string): Option<UDPDataType<udp.Data>> {
-  if (!z.string().ip().safeParse(address).success) {
-    return None
-  }
-
-  const arrayData = receivedData.get(address)
-  if (_.isUndefined(arrayData)) {
-    return None
-  }
-
-  const data = arrayData.pop()
-  if (_.isUndefined(data)) {
-    return None
-  }
-
-  return Some({
-    address: address,
-    body: data.body,
-    port: data.port,
-    date: data.date,
-  })
-}
-
-function oldestData(address: string): Option<UDPDataType<udp.Data>> {
-  if (!z.string().ip().safeParse(address).success) {
-    return None
-  }
-
-  const arrayData = receivedData.get(address)
-  if (_.isUndefined(arrayData)) {
-    return None
-  }
-
-  const data = arrayData.shift()
-  if (_.isUndefined(data)) {
-    return None
-  }
-
-  return Some({
-    address: address,
-    body: data.body,
-    port: data.port,
-    date: data.date,
-  })
-}
-
-export { port, lastestData, oldestData }
-
diff --git a/tsconfig.bun.json b/tsconfig.bun.json
deleted file mode 100644
index 4289b08..0000000
--- a/tsconfig.bun.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-  "compilerOptions": {
-    // Enable latest features
-    "lib": [
-      "ESNext"
-    ],
-    "target": "ESNext",
-    "module": "ESNext",
-    "moduleDetection": "force",
-    "jsx": "react-jsx",
-    "allowJs": true,
-    // Bundler mode
-    "moduleResolution": "bundler",
-    "allowImportingTsExtensions": true,
-    "verbatimModuleSyntax": true,
-    "noEmit": true,
-    // Best practices
-    "strict": true,
-    "skipLibCheck": true,
-    "noFallthroughCasesInSwitch": true,
-    // Some stricter flags
-    "noUnusedLocals": true,
-    "noUnusedParameters": true,
-    "noPropertyAccessFromIndexSignature": true
-  }
-}