Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • hlgr/drawing-app
  • sweng-group-15/drawing-app
2 results
Show changes
Commits on Source (188)
Showing with 9104 additions and 2175 deletions
......@@ -5,11 +5,13 @@
"node": true,
"jest": true
},
"extends": ["eslint:recommended", "prettier"],
"plugins": ["testcafe"],
"extends": ["eslint:recommended", "prettier", "plugin:testcafe/recommended"],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parser": "babel-eslint",
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module"
......
# Created by https://www.gitignore.io/api/vim,node,macos,visualstudiocode
# Edit at https://www.gitignore.io/?templates=vim,node,macos,visualstudiocode
......@@ -10,6 +9,54 @@ src/liowebrtc
src/rtcpeerconnection
src/signalbuddy
src/yjs
src/drawing-crdt
# Temporary benchmark dump files
.dot-seq-add-packets.json
.dot-seq-erase-packets.json
.dot-seq-sync-packets.json
.dot-seq-add-events.json
.dot-seq-erase-events.json
.dot-seq-sync-events.json
.dot-par-add-packets.json
.dot-par-erase-packets.json
.dot-par-sync-packets.json
.dot-par-add-events.json
.dot-par-erase-events.json
.dot-par-sync-events.json
.path-seq-add-packets.json
.path-seq-erase-packets.json
.path-seq-sync-packets.json
.path-seq-add-events.json
.path-seq-erase-events.json
.path-seq-sync-events.json
.path-par-add-packets.json
.path-par-erase-packets.json
.path-par-sync-packets.json
.path-par-add-events.json
.path-par-erase-events.json
.path-par-sync-events.json
.dot-ver-add-packets.json
.dot-ver-erase-packets.json
.dot-ver-sync-packets.json
.dot-ver-add-events.json
.dot-ver-erase-events.json
.dot-ver-sync-events.json
.path-ver-add-packets.json
.path-ver-erase-packets.json
.path-ver-sync-packets.json
.path-ver-add-events.json
.path-ver-erase-events.json
.path-ver-sync-events.json
# Benchmark output files
plots/*.tsv
plots/*.pdf
### macOS ###
# General
......@@ -118,8 +165,10 @@ typings/
.nuxt
# react / gatsby (customised)
public/js/app.js
public/js/queue.js
public/service-worker.js
public/js
public/benchmarks.html
public/assets/fonts/font-awesome
# vuepress build output
.vuepress/dist
......@@ -155,10 +204,6 @@ tags
### VisualStudioCode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
### VisualStudioCode Patch ###
# Ignore all local history of files
......
default:
image: node:12
image: amio/node-chrome
stages:
- fetch
......@@ -8,19 +8,21 @@ stages:
- build
- test
- deploy
- benchmark
submodule_fetch:
stage: fetch
script:
- chmod 600 .drawing-app-deploy.rsa
- git submodule sync --recursive
- GIT_SSH_COMMAND='ssh -i .drawing-app-deploy.rsa -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' git submodule update --init
- GIT_SSH_COMMAND='ssh -i '`pwd`'/.drawing-app-deploy.rsa -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' git submodule update --init --recursive
artifacts:
paths:
- src/liowebrtc
- src/rtcpeerconnection
- src/signalbuddy
- src/yjs
- src/drawing-crdt/pkg
npm_install_prod:
stage: deps
......@@ -31,10 +33,7 @@ npm_install_prod:
artifacts:
paths:
- node_modules
- src/liowebrtc
- src/rtcpeerconnection
- src/signalbuddy
- src/yjs
npm_install:
stage: deps
......@@ -47,8 +46,9 @@ npm_install:
- node_modules
- src/liowebrtc
- src/rtcpeerconnection
- src/signalbuddy
- src/yjs
- src/drawing-crdt/pkg
- src/signalbuddy
format_check:
stage: check
......@@ -70,6 +70,7 @@ build:
- npm_install
script:
- npm run build
- gcc -E -P -traditional-cpp -o /dev/stdout -DFILES_TO_CACHE_LIST=`find public/ -type f "!" -iname service-worker.js -and "!" -name '.*' | cut -c6- | sed 's_._"_' | sed 's/$/",/' | sort | tr -d '\n'` - < src/service-worker.js | npx prettier --parser babel > public/service-worker.js
artifacts:
paths:
- public/
......@@ -79,7 +80,16 @@ test:
dependencies:
- npm_install
script:
- npm test
- npm run test
chrome_test:
stage: test
dependencies:
- npm_install
- build
script:
- npm run start-bg
- npm run test-e2e
deploy:
stage: deploy
......@@ -92,3 +102,20 @@ deploy:
- apt-get update -qq && apt-get install -qq zip
- zip -r application.zip *
- curl -X POST -u "$DEPLOYMENT_USERNAME:$DEPLOYMENT_PASSWORD" $DEPLOYMENT_ENDPOINT -T application.zip
benchmark:
stage: benchmark
dependencies:
- npm_install
only:
- master
script:
- apt-get -y install gnuplot
- npm run build:bench
- cp __benchmarks__/benchmarks.html public/benchmarks.html
- npm run start-bg
- npm run benchmarks
- npm run plot
artifacts:
paths:
- plots/
......@@ -10,3 +10,6 @@
[submodule "src/yjs"]
path = src/yjs
url = git@gitlab.doc.ic.ac.uk:sweng-group-15/yjs.git
[submodule "src/drawing-crdt"]
path = src/drawing-crdt
url = git@gitlab.doc.ic.ac.uk:sweng-group-15/drawing-crdt.git
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
</head>
<body>
<script src="js/benchmarks.js"></script>
</body>
</html>
This diff is collapsed.
export const handshake = Uint8Array.of(
133,
164,
117,
117,
105,
100,
217,
36,
97,
54,
100,
57,
50,
55,
97,
56,
45,
53,
50,
57,
101,
45,
52,
55,
50,
54,
45,
97,
102,
48,
98,
45,
56,
48,
57,
55,
98,
48,
48,
102,
55,
99,
49,
55,
167,
109,
101,
115,
115,
97,
103,
101,
196,
3,
162,
109,
108,
165,
115,
108,
105,
99,
101,
0,
166,
108,
101,
110,
103,
116,
104,
3,
170,
99,
111,
109,
112,
114,
101,
115,
115,
101,
100,
194,
)
export const dotDraw = [[209, 88, 5.0, "#0000ff"]]
export const dotErase = [[0, [[0, 0]]]]
export const pathDraw = [
[229, 147, 5.0, "#0000ff"],
[239, 149, 5.0, "#0000ff"],
[265, 154, 5.0, "#0000ff"],
[329, 158, 5.0, "#0000ff"],
[428, 168, 5.0, "#0000ff"],
[559, 172, 5.0, "#0000ff"],
[689, 176, 5.0, "#0000ff"],
[789, 176, 5.0, "#0000ff"],
[871, 178, 5.0, "#0000ff"],
[915, 179, 5.0, "#0000ff"],
[937, 179, 5.0, "#0000ff"],
[942, 179, 5.0, "#0000ff"],
]
export const pathErase = [
[0, [[0, 0.030367582231477598]]],
[0, [[0, 0.21377102974828613]]],
[0, [[0, 0.2537463508623564]]],
[0, [[0, 0.34615384615384587]]],
[0, [[0, 0.4383613354449363]]],
[0, [[0, 0.5303675822314777]]],
[0, [[0, 0.6221712759429692]]],
[0, [[0, 0.7137710297482863]]],
[0, [[0, 0.8051653782004998]]],
[0, [[0, 0.9383613354449363]]],
[0, [[0, 1]]],
[1, [[0, 0.011716311379342382]]],
[1, [[0, 0.11776520948773353]]],
[1, [[0, 0.24006055181058228]]],
[1, [[0, 0.3107159148890084]]],
[1, [[0, 0.3810746303975673]]],
[1, [[0, 0.4329788671985464]]],
[1, [[0, 0.46835801309405006]]],
[1, [[0, 0.5036636541863274]]],
[1, [[0, 0.5740522382479196]]],
[1, [[0, 0.6441399664465288]]],
[1, [[0, 0.731854882371686]]],
[1, [[0, 0.8021237085400632]]],
[1, [[0, 0.8371448744989799]]],
[1, [[0, 0.88955025220044]]],
[1, [[0, 0.9599984343180302]]],
[1, [[0, 1]]],
[2, [[0, 0.028177027652500065]]],
[2, [[0, 0.03543420592413073]]],
[2, [[0, 0.06582991759489924]]],
[2, [[0, 0.10275381734879]]],
[2, [[0, 0.11799692411252251]]],
[2, [[0, 0.13323648198760243]]],
[2, [[0, 0.16370490408198182]]],
[2, [[0, 0.2154080009026301]]],
[2, [[0, 0.24595364724469834]]],
[2, [[0, 0.27648544742767633]]],
[2, [[0, 0.31247481764398494]]],
[2, [[0, 0.3478072470007028]]],
[2, [[0, 0.3785134252130592]]],
[2, [[0, 0.3938616312677431]]],
[2, [[0, 0.42869266182685783]]],
[2, [[0, 0.44408271983476183]]],
[2, [[0, 0.4594695941376009]]],
[2, [[0, 0.4902337694168022]]],
[2, [[0, 0.505611059005356]]],
[2, [[0, 0.5246181146997148]]],
[2, [[0, 0.5400397300348875]]],
[2, [[0, 0.6047746406708809]]],
[2, [[0, 0.6202304708442001]]],
[2, [[0, 0.6356832087546725]]],
[2, [[0, 0.6535687967630837]]],
[2, [[0, 0.7000469301249926]]],
[2, [[0, 0.7155335204468358]]],
[2, [[0, 0.7484433368793898]]],
[2, [[0, 0.8415551828545537]]],
[2, [[0, 0.8896745156013701]]],
[2, [[0, 0.9207665061568425]]],
[2, [[0, 0.9518463520584276]]],
[2, [[0, 0.9840324922550672]]],
[2, [[0, 1]]],
[3, [[0, 0.01983903263791853]]],
[3, [[0, 0.029876622283678104]]],
[3, [[0, 0.03990912701215377]]],
[3, [[0, 0.0806437862168895]]],
[3, [[0, 0.09070123866218649]]],
[3, [[0, 0.10101007524615979]]],
[3, [[0, 0.11110799523965204]]],
[3, [[0, 0.12120077057322706]]],
[3, [[0, 0.13128840847448436]]],
[3, [[0, 0.15144829885129574]]],
[3, [[0, 0.16152056375068494]]],
[3, [[0, 0.1818098260284825]]],
[3, [[0, 0.20202009896967427]]],
[3, [[0, 0.21211750416023725]]],
[3, [[0, 0.2727084630640253]]],
[3, [[0, 0.29292802997685985]]],
[3, [[0, 0.3030300711783685]]],
[3, [[0, 0.33330532017010783]]],
[3, [[0, 0.3636029076253441]]],
[3, [[0, 0.37371993253130364]]],
[3, [[0, 0.3838317824361028]]],
[3, [[0, 0.40403999188002426]]],
[3, [[0, 0.41413636769223433]]],
[3, [[0, 0.42422760105585006]]],
[3, [[0, 0.43431369907567324]]],
[3, [[0, 0.4443662699271226]]],
[3, [[0, 0.4544931529993546]]],
[3, [[0, 0.46461484324950236]]],
[3, [[0, 0.4747313502489194]]],
[3, [[0, 0.5050498610823838]]],
[3, [[0, 0.5151457223183467]]],
[3, [[0, 0.5353220266951074]]],
[3, [[0, 0.5454024835564785]]],
[3, [[0, 0.5858535321955943]]],
[3, [[0, 0.5959591836309699]]],
[3, [[0, 0.616155025527601]]],
[3, [[0, 0.6463920624411829]]],
[3, [[0, 0.6666385590106888]]],
[3, [[0, 0.6767540304709369]]],
[3, [[0, 0.6969694650467834]]],
[3, [[0, 0.7474179601261248]]],
[3, [[0, 0.7675614683096057]]],
[3, [[0, 0.7776255556078067]]],
[3, [[0, 0.8282626561208872]]],
[3, [[0, 0.8484256216002729]]],
[3, [[0, 0.8584994213492495]]],
[3, [[0, 0.8685681068775302]]],
[3, [[0, 0.9087918074364576]]],
[3, [[0, 0.9188349938933553]]],
[3, [[0, 0.9288730921857218]]],
[3, [[0, 0.9889949697600137]]],
[3, [[0, 0.99974858647489]]],
[3, [[0, 1]]],
[4, [[0, 0.015052512188419602]]],
[4, [[0, 0.03029426962088413]]],
[4, [[0, 0.06839243749770468]]],
[4, [[0, 0.0836292133608997]]],
[4, [[0, 0.0912470672285808]]],
[4, [[0, 0.09886456497394153]]],
[4, [[0, 0.13734696870310906]]],
[4, [[0, 0.14497397901135212]]],
[4, [[0, 0.16022693354357556]]],
[4, [[0, 0.16785287776755597]]],
[4, [[0, 0.2061009857691912]]],
[4, [[0, 0.2213715432205954]]],
[4, [[0, 0.2290062878232259]]],
[4, [[0, 0.23664067642184725]]],
[4, [[0, 0.31287013784360607]]],
[4, [[0, 0.33579551026422]]],
[4, [[0, 0.3434365859114192]]],
[4, [[0, 0.37399731542592607]]],
[4, [[0, 0.3892755376794567]]],
[4, [[0, 0.3969141134976991]]],
[4, [[0, 0.41219019494203474]]],
[4, [[0, 0.47328026274975304]]],
[4, [[0, 0.48854921795242295]]],
[4, [[0, 0.5267153779648435]]],
[4, [[0, 0.5343475426943275]]],
[4, [[0, 0.5419793517647892]]],
[4, [[0, 0.5496108052135158]]],
[4, [[0, 0.5801330634496403]]],
[4, [[0, 0.5877627392618375]]],
[4, [[0, 0.5953920596237392]]],
[4, [[0, 0.610649634073643]]],
[4, [[0, 0.6487873509046499]]],
[4, [[0, 0.6564138281707615]]],
[4, [[0, 0.6640399500759696]]],
[4, [[0, 0.7174128527857359]]],
[4, [[0, 0.7326590547531385]]],
[4, [[0, 0.7402816225030254]]],
[4, [[0, 0.7555256913985305]]],
[4, [[0, 0.8469602239274668]]],
[4, [[0, 0.8621943289183245]]],
[4, [[0, 0.8698108469953234]]],
[4, [[0, 0.8774270087010998]]],
[4, [[0, 0.9078880903271799]]],
[4, [[0, 0.9155024690411608]]],
[4, [[0, 0.9231164909119645]]],
[4, [[0, 0.9307301558520772]]],
[4, [[0, 0.9769418956440951]]],
[4, [[0, 0.9845647300195252]]],
[4, [[0, 0.992187208890867]]],
[4, [[0, 0.9998093322301707]]],
[4, [[0, 1]]],
[5, [[0, 0.03820574873127833]]],
[5, [[0, 0.045884233047770166]]],
[5, [[0, 0.061240109456200745]]],
[5, [[0, 0.1226490440345489]]],
[5, [[0, 0.13032352057732857]]],
[5, [[0, 0.14567137935938093]]],
[5, [[0, 0.15334476144043718]]],
[5, [[0, 0.19170619534531316]]],
[5, [[0, 0.19937738618962128]]],
[5, [[0, 0.2070482114971963]]],
[5, [[0, 0.2453968513383652]]],
[5, [[0, 0.26073374476033434]]],
[5, [[0, 0.26840164189649224]]],
[5, [[0, 0.3067356268350702]]],
[5, [[0, 0.322066651341349]]],
[5, [[0, 0.32973161244332394]]],
[5, [[0, 0.34506043162274563]]],
[5, [[0, 0.39869970096661816]]],
[5, [[0, 0.4063609788597506]]],
[5, [[0, 0.41402188753199426]]],
[5, [[0, 0.4676378950251564]]],
[5, [[0, 0.47529584340574377]]],
[5, [[0, 0.5518548940788806]]],
[5, [[0, 0.5595087511478618]]],
[5, [[0, 0.56716223496407]]],
[5, [[0, 0.5824680819078778]]],
[5, [[0, 0.6686904305673842]]],
[5, [[0, 0.6917061953453132]]],
[5, [[0, 0.7070482114971963]]],
[5, [[0, 0.7766873397479431]]],
[5, [[0, 0.7923021861323849]]],
[5, [[0, 0.7999923098661218]]],
[5, [[0, 0.8076820697480561]]],
[5, [[0, 0.8614794103478556]]],
[5, [[0, 0.8768764254973112]]],
[5, [[0, 0.8845743850827851]]],
[5, [[0, 0.8922719794659787]]],
[5, [[0, 0.9458689803376649]]],
[5, [[0, 0.9612817605421127]]],
[5, [[0, 0.9689875986837584]]],
[5, [[0, 1]]],
[6, [[0, 0.029749843554381775]]],
[6, [[0, 0.059749843554381774]]],
[6, [[0, 0.06974984355438178]]],
[6, [[0, 0.13974984355438178]]],
[6, [[0, 0.14974984355438178]]],
[6, [[0, 0.15974984355438177]]],
[6, [[0, 0.16974984355438177]]],
[6, [[0, 0.17974984355438178]]],
[6, [[0, 0.21974984355438176]]],
[6, [[0, 0.22974984355438177]]],
[6, [[0, 0.23974984355438178]]],
[6, [[0, 0.2497498435543818]]],
[6, [[0, 0.3197498435543818]]],
[6, [[0, 0.3397498435543818]]],
[6, [[0, 0.3497498435543818]]],
[6, [[0, 0.35974984355438183]]],
[6, [[0, 0.468997487421324]]],
[6, [[0, 0.48899748742132404]]],
[6, [[0, 0.49899748742132405]]],
[6, [[0, 0.518997487421324]]],
[6, [[0, 0.6277371993328519]]],
[6, [[0, 0.6377371993328519]]],
[6, [[0, 0.6477371993328519]]],
[6, [[0, 0.6677371993328519]]],
[6, [[0, 0.7777371993328519]]],
[6, [[0, 0.7877371993328519]]],
[6, [[0, 0.8077371993328519]]],
[6, [[0, 0.9377371993328519]]],
[6, [[0, 0.957737199332852]]],
[6, [[0, 0.977737199332852]]],
[6, [[0, 1]]],
[7, [[0, 0.08434122461529223]]],
[7, [[0, 0.09736319249220814]]],
[7, [[0, 0.12177670236609432]]],
[7, [[0, 0.13398291047706393]]],
[7, [[0, 0.2560176149231152]]],
[7, [[0, 0.26820494288749264]]],
[7, [[0, 0.2803919084377965]]],
[7, [[0, 0.30476475227840155]]],
[7, [[0, 0.42434250381943905]]],
[7, [[0, 0.4364947880419225]]],
[7, [[0, 0.44864670195280104]]],
[7, [[0, 0.4607982453870106]]],
[7, [[0, 0.5822932659066377]]],
[7, [[0, 0.5944407226857343]]],
[7, [[0, 0.6065878068658583]]],
[7, [[0, 0.7298557216513387]]],
[7, [[0, 0.7420139098657976]]],
[7, [[0, 0.7541717301678039]]],
[7, [[0, 0.7663291824206042]]],
[7, [[0, 0.8284299052782537]]],
[7, [[0, 0.8406001691299525]]],
[7, [[0, 0.8649396036740605]]],
[7, [[0, 0.9753340606845997]]],
[7, [[0, 0.9875148632580261]]],
[7, [[0, 0.9996953030971739]]],
[7, [[0, 1]]],
[8, [[0, 0.022133273001338587]]],
[8, [[0, 0.20418547065439502]]],
[8, [[0, 0.22693303640624127]]],
[8, [[0, 0.24968001232099726]]],
[8, [[0, 0.272426398521291]]],
[8, [[0, 0.47595107564942674]]],
[8, [[0, 0.5214835194176608]]],
[8, [[0, 0.5442488489860375]]],
[8, [[0, 0.5670135839399206]]],
[8, [[0, 0.5897777244732638]]],
[8, [[0, 0.749110080215568]]],
[8, [[0, 0.7718694720767475]]],
[8, [[0, 0.7946282711542776]]],
[8, [[0, 0.8173864776180217]]],
[8, [[0, 1]]],
[9, [[0, 0.04431747070173535]]],
[9, [[0, 0.0897720161562808]]],
[9, [[0, 0.18068110706537172]]],
[9, [[0, 0.4988629252471899]]],
[9, [[0, 0.5897720161562808]]],
[9, [[0, 0.6352265616108262]]],
[9, [[0, 0.7261356525199172]]],
[9, [[0, 1]]],
[10, [[0, 1]]],
[11, [[0, 1]]],
]
import puppeteer from "puppeteer-core"
import fs from "fs"
;(async () => {
const browser = await puppeteer.launch({
executablePath: "google-chrome",
headless: true,
args: [
"--js-flags=--expose-gc",
"--no-sandbox",
"--enable-precise-memory-info",
],
})
const page = await browser.newPage()
const done = new Promise((resolve) => {
page.on("console", (msg) => {
if (msg.type() == "debug") {
process.stderr.write(msg.text())
} else if (msg.type() == "info") {
const { filename, title, iterations, results } = JSON.parse(msg.text())
if (title) {
const columns = ["iterations"]
for (const title of results) {
columns.push(`${title}_timeLoc`)
columns.push(`${title}_encodeRAM`)
columns.push(`${title}_packets`)
columns.push(`${title}_size`)
columns.push(`${title}_timeRem`)
columns.push(`${title}_decodeRAM`)
columns.push(`${title}_events`)
}
fs.writeFileSync(
filename,
`# Benchmark: ${title}\n# ${columns.join("\t")}\n`,
)
} else {
const columns = [iterations]
for (const title in results) {
const {
timeLoc,
encodeRAM,
packets,
size,
timeRem,
decodeRAM,
events,
} = results[title]
columns.push(timeLoc)
columns.push(encodeRAM)
columns.push(packets)
columns.push(size)
columns.push(timeRem)
columns.push(decodeRAM)
columns.push(events)
}
fs.appendFileSync(filename, `${columns.join("\t")}\n`)
}
} else if (msg.type() == "log") {
if (msg.text().startsWith("# failure")) {
resolve()
}
process.stdout.write(msg.text() + "\n")
}
})
})
await page.goto("http://localhost:3000/benchmarks.html").catch(console.error)
await done
await browser.close()
})()
import { Selector } from "testcafe"
const host = "127.0.0.1"
const port = process.env.PORT || 3000
fixture`Peer 1`.page`${host}:${port}`
const idAppearTimeout = 1000
const syncTimeout = 5000
const selectorOptions = { timeout: 1000 }
test("Connection id appears", async (t) => {
const userId = async () =>
await Selector("#user-avatar")
.child(1)
.addCustomDOMProperties({ innerHTML: (el) => el.innerHTML })
.with(selectorOptions).innerHTML
await t
.wait(idAppearTimeout)
.expect((await userId()).length)
.gt(0)
})
test("Clicking and dragging on canvas creates a single child element", async (t) => {
const canvas = Selector("#canvas").with(selectorOptions)
await t
.drag(canvas, 10, 10)
.wait(syncTimeout)
.expect(canvas.childElementCount)
// first draw also creates last recognised path placeholder
.eql(2)
})
import { Selector } from "testcafe"
const host = "127.0.0.1"
const port = 3000
fixture`Peer 2`.page`${host}:${port}`
const idAppearTimeout = 1000
const syncTimeout = 15000
const selectorOptions = { timeout: 1000 }
test("Connection id appears", async (t) => {
const userId = async () =>
await Selector("#user-avatar")
.child(1)
.addCustomDOMProperties({ innerHTML: (el) => el.innerHTML })
.with(selectorOptions).innerHTML
await t
.wait(idAppearTimeout)
.expect((await userId()).length)
.gt(0)
})
test("Canvas eventually gets a child element", async (t) => {
const canvas = Selector("#canvas").with(selectorOptions)
await t.expect(canvas.childElementCount).eql(1, { timeout: syncTimeout })
})
import recognizeFromPoints, {
Shapes,
computeMatrixCoefficients,
} from "../src/shapes"
import recognizeFromPoints, { Shapes } from "../src/shapes"
describe("shape recognition", () => {
describe("general", () => {
......@@ -12,42 +9,45 @@ describe("shape recognition", () => {
})
})
describe("matrix coefficients", () => {
test("should compute coefficients correctly", () => {
const points = [[0, 0], [0, 5], [0, 10], [10, 5]]
const coefficients = computeMatrixCoefficients(points)
expect(coefficients).toStrictEqual([
[1 / 4, 1 / 4, 1 / 4],
[0, 0, 0],
[0, 1 / 4, 0],
])
})
})
describe("lines", () => {
test("should recognize a simple horizontal line", () => {
const points = [[0, 0], [100, 0]]
const points = [
[0, 0],
[100, 0],
]
const result = recognizeFromPoints(points)
expect(result.shape).toBe(Shapes.line)
expect(result.angle).toBe(0)
expect(result.firstPoint).toStrictEqual([0, 0])
expect(result.lastPoint).toStrictEqual([100, 0])
})
test("should recognize a simple vertical line", () => {
const points = [[0, 50], [0, -100]]
const points = [
[0, 50],
[0, -100],
]
const result = recognizeFromPoints(points)
expect(result.shape).toBe(Shapes.line)
expect(result.angle).toBe(90)
expect(result.firstPoint).toStrictEqual([0, 50])
expect(result.lastPoint).toStrictEqual([0, -100])
})
test("should recognize a slightly curve horizontal line", () => {
const points = [[0, 0], [30, 5], [100, 2]]
const points = [
[0, 0],
[30, 5],
[100, 0],
]
const result = recognizeFromPoints(points)
expect(result.shape).toBe(Shapes.line)
expect(result.angle).toBe(0)
})
test("should not recognize a really curved horizontal line", () => {
const points = [[0, 0], [30, 30], [100, -4]]
test("should not recognize a heavily curved horizontal line", () => {
const points = [
[0, 0],
[30, 30],
[100, -4],
]
const result = recognizeFromPoints(points)
expect(result.shape).not.toBe(Shapes.line)
})
......@@ -72,7 +72,6 @@ describe("shape recognition", () => {
]
const result = recognizeFromPoints(points)
expect(result.shape).toBe(Shapes.line)
expect(result.angle).toBe(0)
})
test("should recognize a long vertical line", () => {
......@@ -115,7 +114,6 @@ describe("shape recognition", () => {
]
const result = recognizeFromPoints(points)
expect(result.shape).toBe(Shapes.line)
expect(result.angle).toBe(90)
})
test("should recognize a line at 20 degrees", () => {
......@@ -192,18 +190,141 @@ describe("shape recognition", () => {
const result = recognizeFromPoints(points)
expect(result.shape).toBe(Shapes.line)
expect(result.angle).toBe(20)
})
})
describe("rectangles", () => {
test("should recognize simple rectangle", () => {
const points = [[-10, -10], [10, -10], [10, 10], [-10, 10]]
test("should recognize line 1", () => {
const points = [
[380, 355],
[380, 356],
[381, 355],
[383, 354],
[386, 352],
[391, 349],
[395, 346],
[400, 343],
[405, 339],
[411, 335],
[416, 332],
[425, 325],
[433, 318],
[440, 312],
[447, 306],
[454, 300],
[462, 293],
[471, 283],
[479, 274],
[487, 266],
[498, 255],
[509, 244],
[520, 235],
[531, 226],
[539, 218],
[543, 215],
[550, 208],
[558, 203],
[563, 199],
[567, 196],
[571, 193],
[575, 190],
[577, 189],
[578, 188],
[579, 187],
[580, 187],
[580, 187],
[581, 187],
[581, 186],
]
const result = recognizeFromPoints(points)
expect(result.shape).toBe(Shapes.rectangle)
expect(result.shape).toBe(Shapes.line)
})
test("should recognize rectangle with many points", () => {
test("should recognize line 2", () => {
const points = [
[648, 509],
[648, 509],
[648, 509],
[646, 509],
[641, 509],
[634, 509],
[628, 509],
[608, 509],
[591, 509],
[571, 509],
[554, 509],
[534, 509],
[513, 505],
[486, 499],
[462, 495],
[454, 494],
[433, 490],
[413, 488],
[396, 485],
[382, 485],
[368, 482],
[360, 482],
[356, 482],
[348, 479],
[341, 479],
[336, 478],
[331, 478],
[329, 478],
[327, 477],
[326, 476],
[326, 476],
[325, 476],
[325, 476],
[325, 476],
[325, 476],
[323, 476],
[322, 476],
[320, 476],
[319, 476],
[318, 476],
[316, 476],
[315, 475],
[315, 475],
[314, 475],
[314, 475],
[313, 475],
]
const result = recognizeFromPoints(points)
expect(result.shape).toBe(Shapes.line)
})
test("should recognize line 3", () => {
const points = [
[204, 590],
[205, 590],
[208, 584],
[219, 574],
[254, 534],
[276, 500],
[305, 456],
[334, 410],
[346, 388],
[376, 336],
[404, 284],
[430, 238],
[454, 197],
[458, 190],
[474, 160],
[483, 142],
[485, 138],
[492, 126],
[495, 121],
[498, 117],
[499, 115],
[500, 114],
[500, 114],
[500, 113],
]
const result = recognizeFromPoints(points)
expect(result.shape).toBe(Shapes.line)
})
})
describe("rectangles", () => {
test("should recognize simple rectangle", () => {
const points = [
[0, 0],
[5, 0],
......@@ -232,25 +353,272 @@ describe("shape recognition", () => {
})
test("should not recognize rectangle with non-rectangular points", () => {
const points = [[5, 1], [23, 0], [10, 54], [0, 10]]
const points = [
[5, 1],
[23, 0],
[10, 54],
[0, 10],
]
const result = recognizeFromPoints(points)
expect(result.shape).not.toBe(Shapes.rectangle)
})
test("should not recognize unclosed rectangle", () => {
const points = [[-10, -10], [10, -10], [10, 10]]
const points = [
[-10, -10],
[10, -10],
[10, 10],
]
const result = recognizeFromPoints(points)
expect(result.shape).not.toBe(Shapes.rectangle)
})
test("should recognize almost-closed rectangle", () => {
const points = [[-10, -10], [10, -10], [10, 10], [-9, 9]]
const points = [
[0, 0],
[5, 0],
[10, 0],
[10, 5],
[10, 10],
[5, 10],
[0, 8],
]
const result = recognizeFromPoints(points)
expect(result.shape).toBe(Shapes.rectangle)
})
test("should recognize half-closed rectangle", () => {
const points = [[-10, -10], [10, -10], [10, 10], [-1, -9]]
const points = [
[380, 503],
[379, 503],
[379, 503],
[379, 498],
[379, 491],
[379, 471],
[379, 468],
[379, 457],
[379, 440],
[379, 428],
[379, 412],
[379, 398],
[379, 384],
[379, 373],
[379, 369],
[379, 361],
[379, 354],
[379, 349],
[379, 346],
[379, 344],
[379, 343],
[379, 342],
[379, 341],
[381, 340],
[385, 340],
[389, 340],
[398, 340],
[407, 340],
[418, 340],
[429, 340],
[440, 340],
[451, 340],
[463, 340],
[476, 342],
[488, 343],
[502, 345],
[515, 348],
[520, 349],
[531, 350],
[540, 351],
[549, 352],
[552, 353],
[557, 354],
[558, 355],
[560, 355],
[560, 355],
[560, 355],
[561, 355],
[561, 356],
[561, 356],
[561, 356],
[561, 357],
[561, 360],
[561, 363],
[561, 368],
[561, 377],
[561, 388],
[561, 399],
[561, 406],
[561, 414],
[561, 423],
[561, 432],
[561, 441],
[561, 447],
[561, 452],
[561, 459],
[561, 463],
[561, 468],
[561, 471],
[561, 475],
[561, 478],
[561, 479],
[561, 480],
[561, 480],
[561, 481],
[561, 482],
[561, 482],
[561, 483],
[560, 483],
[560, 483],
[558, 484],
[556, 485],
[551, 487],
[546, 488],
[540, 490],
[533, 492],
[522, 493],
[513, 494],
[502, 496],
[491, 497],
[480, 497],
[466, 499],
[452, 500],
[447, 500],
[436, 500],
[427, 501],
[418, 501],
[412, 503],
[407, 503],
[402, 504],
[400, 504],
[398, 504],
[398, 504],
[397, 504],
[396, 504],
]
const result = recognizeFromPoints(points)
expect(result.shape).toBe(Shapes.rectangle)
})
test("should recognize half-closed rectangle 2", () => {
const points = [
[294, 477],
[293, 477],
[293, 477],
[293, 473],
[293, 469],
[293, 465],
[293, 459],
[293, 455],
[293, 451],
[293, 444],
[293, 437],
[293, 431],
[293, 423],
[293, 414],
[293, 403],
[293, 394],
[293, 391],
[293, 384],
[293, 379],
[293, 376],
[293, 373],
[293, 372],
[293, 371],
[293, 370],
[293, 370],
[293, 369],
[294, 369],
[295, 368],
[298, 368],
[303, 367],
[308, 366],
[317, 364],
[328, 362],
[341, 360],
[358, 357],
[375, 355],
[392, 352],
[412, 350],
[436, 348],
[457, 346],
[480, 344],
[501, 342],
[518, 342],
[535, 340],
[539, 339],
[551, 339],
[559, 338],
[568, 337],
[573, 337],
[576, 337],
[578, 337],
[579, 337],
[579, 337],
[580, 337],
[580, 337],
[581, 337],
[581, 338],
[581, 341],
[581, 346],
[581, 349],
[581, 358],
[579, 366],
[578, 373],
[576, 382],
[575, 386],
[571, 403],
[571, 407],
[568, 420],
[567, 424],
[565, 430],
[562, 437],
[561, 442],
[559, 447],
[558, 450],
[557, 452],
[556, 454],
[556, 456],
[555, 458],
[555, 459],
[554, 460],
[554, 461],
[553, 462],
[553, 462],
[553, 463],
[552, 463],
[552, 463],
[552, 464],
[552, 464],
[551, 464],
[550, 465],
[549, 465],
[544, 466],
[541, 467],
[534, 468],
[527, 469],
[521, 470],
[512, 472],
[509, 472],
[500, 474],
[493, 475],
[485, 476],
[478, 477],
[471, 478],
[465, 479],
[460, 480],
[454, 481],
[450, 482],
[446, 483],
[442, 483],
[439, 483],
[437, 484],
[436, 484],
[435, 484],
[434, 484],
[433, 484],
[433, 484],
[433, 484],
]
const result = recognizeFromPoints(points)
expect(result.shape).toBe(Shapes.rectangle)
})
......
This diff is collapsed.
......@@ -13,43 +13,69 @@
"build": "webpack --config webpack.prod.js",
"build:analyze": "webpack --env.analyze --config webpack.prod.js",
"build:dev": "webpack --config webpack.dev.js",
"build:bench": "webpack --config webpack.bench.js",
"watch": "webpack --watch --config webpack.dev.js",
"start": "node --experimental-modules src/server.js",
"test": "jest --testPathIgnorePatterns src/liowebrtc src/rtcpeerconnection src/signalbuddy src/yjs",
"test-changed": "jest --only-changed --testPathIgnorePatterns src/liowebrtc src/rtcpeerconnection src/signalbuddy src/yjs",
"test-coverage": "jest --coverage --testPathIgnorePatterns src/liowebrtc src/rtcpeerconnection src/signalbuddy src/yjs",
"test": "jest --testPathIgnorePatterns src/liowebrtc src/rtcpeerconnection src/signalbuddy src/yjs src/drawing-crdt",
"test-changed": "jest --only-changed --testPathIgnorePatterns src/liowebrtc src/rtcpeerconnection src/signalbuddy src/yjs src/drawing-crdt",
"test-coverage": "jest --coverage --testPathIgnorePatterns src/liowebrtc src/rtcpeerconnection src/signalbuddy src/yjs src/drawing-crdt",
"benchmarks": "node --experimental-modules __benchmarks__/puppeteer.js | npx tap-summary --no-progress",
"test-e2e:peer1": "testcafe chrome:headless __e2e_tests__/peer1.e2e.js",
"test-e2e:peer2": "testcafe chrome:headless __e2e_tests__/peer2.e2e.js",
"test-e2e": "run-p test-e2e:*",
"test-e2e-start": "run-s start-bg test-e2e",
"start-bg": "npm run start > /dev/null 2>&1 &",
"format": "prettier --ignore-path .gitignore --check --write '**/*.{html,js,json,md}'",
"format-check": "prettier --ignore-path .gitignore --check '**/*.{html,js,json,md}'",
"lint": "eslint --ignore-path .gitignore '**/*.js'",
"validate": "npm ls"
"validate": "npm ls",
"plot": "find plot-scripts/ -maxdepth 1 -type f -name '*.p' -exec gnuplot {} \\;"
},
"dependencies": {
"@ungap/event-target": "^0.1.0",
"d3-shape": "^1.3.5",
"@xmpp/client": "^0.9.2",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"liowebrtc": "file:src/liowebrtc",
"pako": "^1.0.10",
"signalbuddy": "file:src/signalbuddy",
"rtcpeerconnection": "file:src/rtcpeerconnection",
"uuid": "^3.3.3",
"webrtc-adapter": "^7.3.0",
"what-the-pack": "^2.0.3",
"y-array": "^10.1.4",
"y-map": "^10.1.3",
"y-memory": "^8.0.9",
"yjs": "file:src/yjs"
"uuid": "^3.3.3"
},
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.6.0",
"@fortawesome/fontawesome-free": "^5.12.0",
"@ungap/event-target": "^0.1.0",
"array-flat-polyfill": "^1.0.1",
"babel-eslint": "^10.0.3",
"chalk": "^3.0.0",
"css-loader": "^3.4.1",
"d3-shape": "^1.3.5",
"drawing-crdt": "file:src/drawing-crdt/pkg",
"eslint": "^6.5.1",
"eslint-config-prettier": "^6.5.0",
"eslint-plugin-testcafe": "^0.2.1",
"fastbitset": "^0.2.8",
"file-loader": "^5.0.2",
"humanhash": "^1.0.4",
"jdenticon": "^2.2.0",
"jest": "^24.9.0",
"liowebrtc": "file:src/liowebrtc",
"npm-run-all": "^4.1.5",
"pako": "^1.0.10",
"prettier": "^1.18.2",
"puppeteer-core": "^2.0.0",
"rtcpeerconnection": "file:src/rtcpeerconnection",
"style-loader": "^1.1.2",
"tap-summary": "^4.0.0",
"testcafe": "^1.5.0",
"webpack": "^4.41.0",
"webpack-bundle-analyzer": "^3.6.0",
"webpack-cli": "^3.3.9",
"webpack-merge": "^4.2.2"
"webpack-merge": "^4.2.2",
"webrtc-adapter": "^7.3.0",
"what-the-pack": "^2.0.3",
"y-array": "^10.1.4",
"y-map": "^10.1.3",
"y-memory": "^8.0.9",
"yjs": "file:src/yjs",
"zora": "^3.1.8"
},
"pre-commit": [
"lint",
......
set xlabel "Iterations"
set ylabel "Time [ms]"
set title "addPath() performance scalability"
set key inside bottom right
set terminal dumb size 120, 30
set autoscale
plot "plots/dot-seq-benchmark.tsv" using 1:($2/(1e6*$1)) with lines title "dot [sequential]"
set terminal pdf
set output "plots/dot-seq-benchmark.pdf"
plot "plots/dot-seq-benchmark.tsv" using 1:($2/(1e6*$1)) with lines title "dot [sequential]"
public/favicon.ico

1.12 KiB

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 417.7 150.7" style="enable-background:new 0 0 417.7 150.7;" xml:space="preserve">
<style type="text/css">
.st0{fill:#003C70;}
</style>
<path class="st0" d="M28.4,68.2V30.3h7.4v37.9H28.4z"/>
<path class="st0" d="M46.7,44.3h0.1c1.8-2.4,5.2-3.8,8.3-3.8c3.3,0,6.2,1.4,7.8,3.8c2.2-2.2,5.6-3.8,8.8-3.8c6-0.1,9.1,3.7,9.2,9.9
v17.8h-7V51.7c0-3.1-1.1-6.4-4.5-6.4c-3.4,0-5.5,2.1-5.5,6.8v16.2h-7V51.7c0-3.8-1.6-6.4-4.6-6.4c-3.3,0-5.4,2.3-5.4,6.9v16h-7V41.1
h7V44.3z"/>
<path class="st0" d="M98.5,44.8c4,0,6,4.7,6,9.3c0,4.8-1.6,10.4-6.3,10.4c-3.8,0-6.5-3.8-6.5-9.5C91.8,48.7,94.1,44.8,98.5,44.8z
M91.8,41.1h-7v40.7h7V64.8c2,2.4,4.7,4,7.9,4c7.5,0,12.3-7.6,12.3-14.8c0-6-3.4-13.6-11.7-13.6c-3.2,0-6.6,1.6-8.4,4.4h-0.1V41.1z"
/>
<path class="st0" d="M122,51.4c-0.1-3.6,1.7-6.9,5.8-6.9c3.5,0,4.9,2.8,4.6,6.9H122z M139,55.3c0.5-8.1-2.9-14.8-11.1-14.8
c-7.5,0-13.5,5.3-13.5,13.7c0,8.9,6,14.7,13.9,14.7c3,0,6.8-0.9,10.3-3l-2-3.8c-1.7,1.2-4.5,2.2-7.1,2.2c-4.4,0-7.9-3.8-7.7-8.9H139
z"/>
<path class="st0" d="M149.4,45.9h0.1l1.4-2.1c0.8-1.1,2.4-3.3,4.5-3.3c1.6,0,3.3,0.9,4.8,2.4l-2.6,5c-1.2-0.6-1.9-0.9-3.3-0.9
c-2.4,0-4.8,2-4.8,7.9v13.4h-7V41.1h7V45.9z"/>
<path class="st0" d="M169.4,41.1v27.1h-7V41.1H169.4z M161.7,33c0-2.1,1.7-4.2,4.1-4.2c2.4,0,4.3,2.1,4.3,4.2c0,2.3-1.6,4.5-4.2,4.5
C163.4,37.5,161.7,35.3,161.7,33z"/>
<path class="st0" d="M188.5,52.5c0.5,8-3.1,11.5-5.9,11.5c-1.7,0-3.2-1.6-3.2-4c0-3.1,1.7-5.1,5.2-6.2L188.5,52.5z M188.4,64.2
c0,1.5,0.2,3,0.7,4h7.4c-0.8-1.9-1.1-4.4-1.1-6.6V50.5c0-8.5-6-10.1-10.8-10.1c-3.6,0-6.9,0.9-10.1,3.7l2.3,3.4c1.8-1.6,4-2.8,7-2.8
c2.3,0,4.4,1.6,4.8,4.1l-6.2,1.9c-6.1,1.8-9.8,4.7-9.8,9.9c0,5,3.4,8.2,7.5,8.2c2.4,0,4.8-1.7,6.8-3.3L188.4,64.2z"/>
<path class="st0" d="M199.8,68.2V28.4h7v39.8H199.8z"/>
<path class="st0" d="M253.1,37.1c-1.8-1-4.8-2.1-7.7-2.1c-7.6,0-13.1,5.5-13.1,14.1c0,9,6.1,14.3,13.3,14.3c2.9,0,5.5-0.8,7.4-1.9
l2.1,4.7c-2.3,1.4-6.2,2.6-9.8,2.6c-12.8,0-20.9-8.7-20.9-19.8c0-10.4,8-19.4,21-19.4c3.9,0,7.4,1.4,10,2.9L253.1,37.1z"/>
<path class="st0" d="M269.1,64.8c-5,0-6.4-5.7-6.4-10.5c0-4.5,1.6-9.9,6.4-9.9c4.9,0,6.4,5.4,6.4,9.9
C275.5,59.1,274.2,64.8,269.1,64.8z M269.1,68.9c8.3,0,13.9-6.1,13.9-14.5c0-8.8-6.7-13.9-13.9-13.9c-7.1,0-13.8,5.1-13.8,13.9
C255.3,62.7,260.8,68.9,269.1,68.9z"/>
<path class="st0" d="M286,68.2V28.4h7v39.8H286z"/>
<path class="st0" d="M297.4,68.2V28.4h7v39.8H297.4z"/>
<path class="st0" d="M314.9,51.4c-0.1-3.6,1.7-6.9,5.7-6.9c3.5,0,4.9,2.8,4.6,6.9H314.9z M331.9,55.3c0.5-8.1-2.9-14.8-11.1-14.8
c-7.5,0-13.5,5.3-13.5,13.7c0,8.9,6,14.7,13.9,14.7c3,0,6.8-0.9,10.3-3l-2-3.8c-1.7,1.2-4.5,2.2-7.1,2.2c-4.4,0-7.9-3.8-7.7-8.9
H331.9z"/>
<path class="st0" d="M372.2,51.4c-0.1-3.6,1.7-6.9,5.8-6.9c3.5,0,4.9,2.8,4.6,6.9H372.2z M389.2,55.3c0.5-8.1-2.9-14.8-11.1-14.8
c-7.5,0-13.5,5.3-13.5,13.7c0,8.9,6,14.7,13.9,14.7c3,0,6.8-0.9,10.3-3l-2-3.8c-1.7,1.2-4.5,2.2-7.1,2.2c-4.4,0-7.9-3.8-7.7-8.9
H389.2z"/>
<path class="st0" d="M348.3,44.8c4.2,0,6.4,4.4,6.4,9.1c0,5.4-2,10.6-6.7,10.6c-4.1,0-6.1-5.1-6.1-10.4
C342,48.9,343.8,44.8,348.3,44.8z M361.7,41.1h-7v3.3h-0.1c-1.5-2.4-4.6-4-7.9-4c-7.2,0-12.2,6.8-12.2,13.9
c0,8.7,4.6,14.5,11.6,14.5c4,0,6.8-2.3,8.5-4.6h0.1v3.6c0,6.3-3.6,9.2-8.2,9.2c-3.6,0-6.6-0.7-9.2-2.3l-1.4,4.4
c3.1,1.6,7.1,2.6,11.1,2.6c7.9,0,14.7-4,14.7-16V41.1z"/>
<path class="st0" d="M28.4,84.5h7.5v32.8h15.8v5.1H28.4V84.5z"/>
<path class="st0" d="M92.8,98.5c2.5-2.6,6-3.8,9.5-3.8c6.5,0,9.6,3.5,9.6,10.3v17.5h-7.1v-16.6c0-3.8-1.7-6.3-5.6-6.3
c-3.6,0-6.4,2.3-6.4,6.8v16.2h-7.1V95.3h7V98.5z"/>
<path class="st0" d="M130.2,99c4.4,0,6.7,4.4,6.7,9.1c0,5.4-2.1,10.6-7.1,10.6c-4.3,0-6.4-5.1-6.4-10.4S125.4,99,130.2,99z
M136.9,122.4h7.1V82.6h-7.1v15.9h-0.1c-1.7-2.4-4.9-3.8-8.5-3.8c-7.4,0-12.7,6.8-12.7,13.9c0,8.7,4.8,14.5,12.1,14.5
c4.3,0,7.2-2.3,9-4.6h0.1V122.4z"/>
<path class="st0" d="M162.3,119c-5.3,0-6.7-5.7-6.7-10.5c0-4.5,1.7-9.9,6.7-9.9c5.2,0,6.8,5.4,6.8,9.9
C169,113.3,167.6,119,162.3,119z M162.3,123.1c8.7,0,14.6-6.1,14.6-14.5c0-8.8-7.1-13.9-14.6-13.9c-7.4,0-14.5,5.1-14.5,13.9
C147.7,116.9,153.6,123.1,162.3,123.1z"/>
<path class="st0" d="M187.7,98.5c2.5-2.6,6-3.8,9.5-3.8c6.5,0,9.6,3.5,9.6,10.3v17.5h-7.1v-16.6c0-3.8-1.7-6.3-5.6-6.3
c-3.6,0-6.4,2.3-6.4,6.8v16.2h-7.1V95.3h7V98.5z"/>
<path class="st0" d="M67.2,119c-5.3,0-6.7-5.7-6.7-10.5c0-4.5,1.7-9.9,6.7-9.9c5.2,0,6.8,5.4,6.8,9.9C74,113.3,72.6,119,67.2,119z
M67.2,123.1c8.7,0,14.6-6.1,14.6-14.5c0-8.8-7.1-13.9-14.6-13.9c-7.4,0-14.5,5.1-14.5,13.9C52.7,116.9,58.6,123.1,67.2,123.1z"/>
</svg>
......@@ -6,11 +6,6 @@
<link rel="shortcut icon" href="logo.png" />
<link rel="apple-touch-icon" href="logo.png" />
<link rel="stylesheet" href="styles.css" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<script>
if (navigator.serviceWorker) {
navigator.serviceWorker.register("service-worker.js").then(
......@@ -25,17 +20,10 @@
</script>
</head>
<body>
<div style="display:none">
Your client ID: <input id="user-id" type="text" value="" readonly="" />
</div>
<div style="display:none">
Enter peer ID: <input id="peer-id" type="text" value="" />
<button id="peer-connect">Connect</button>
</div>
<div id="top-panel">
<div class="top-bar">
<div class="dropdown">
<button class="dropdown-peers"><i class="fa fa-bars"></i></button>
<button class="dropdown-peers"><i class="fas fa-bars"></i></button>
<div class="peers">
<ul id="connected-peers">
No peers are connected
......@@ -57,11 +45,11 @@
size="25"
color="gray"
/>
<button id="room-connect">Connect <i class="fa fa-link"></i></button>
<button id="room-connect">Connect <i class="fas fa-link"></i></button>
</div>
<div id="tools-panel">
<button id="pen-tool" class="selected">
<i class="fa fa-paint-brush"></i>
<button id="pen-tool" class="selectable-tool selected">
<i class="fas fa-paint-brush"></i>
</button>
<div id="pen-properties" class="properties">
<div class="pen-contents">
......@@ -86,8 +74,7 @@
<input
type="range"
min="1"
max="100"
value="10"
max="10"
class="slider"
id="range"
/>
......@@ -192,19 +179,51 @@
<b>Other colours</b>
</div>
<label id="colours">
<input id="other-colours" type="color" value="#0000ff" />
<input id="other-colours" type="color" />
</label>
</div>
</div>
</div>
<button id="eraser-tool"><i class="fa fa-eraser"></i></button>
<div id="connected-room-info">
You are connected to a room: <span id="connected-room-id"></span>
<button id="eraser-tool" class="selectable-tool">
<i class="fas fa-eraser"></i>
</button>
<button id="dragging-tool" class="selectable-tool">
<i class="far fa-hand-paper"></i>
</button>
<button id="canvas-center" class="selectable-tool">
<i class="fas fa-crosshairs"></i>
</button>
<button id="recognition-mode" class="selectable-tool">
<i class="fas fa-square"></i>
</button>
<div class="spacer"></div>
<div id="status-info">
<button id="fast-undo-tool" class="disabled selectable-tool">
<i class="fas fa-fast-backward"></i>
</button>
<button id="undo-tool" class="disabled selectable-tool">
<i class="fas fa-step-backward"></i>
</button>
<div id="connected-room-info">
Room:&nbsp;
<span id="connected-room-id"></span>
</div>
<div id="user-avatar"></div>
<div id="imperial-logo">
<img
src="imperial.svg"
alt="Imperial College London Logo"
height="42px"
/>
</div>
</div>
</div>
</div>
<svg id="canvas"></svg>
<div id="canvas-container">
<svg id="canvas"></svg>
</div>
<script src="js/app.js"></script>
</body>
......
......@@ -14,11 +14,21 @@ body {
flex-direction: column;
}
#canvas {
#canvas-container {
width: calc(100vw - 8px);
background-color: white;
border: 4px solid red;
flex-grow: 1;
position: relative;
overflow: hidden;
}
#canvas {
position: absolute;
left: -5000px;
top: -5000px;
width: 10000px;
height: 10000px;
}
#tools-panel {
......@@ -27,11 +37,18 @@ body {
align-items: center;
}
.spacer {
flex: 1;
}
#connected-room-info {
display: none;
color: white;
flex: 1;
text-align: right;
display: flex;
align-items: center;
background-color: #4f4f4fb7;
border-radius: 4px;
justify-content: center;
padding: 0.75em;
}
button.selected {
......@@ -64,7 +81,7 @@ button.selected {
cursor: pointer;
border-radius: 4px;
transition-duration: 0.4s;
height: 100%;
height: 36px;
width: 36px;
}
......@@ -75,7 +92,7 @@ button.selected {
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 999;
padding: 16px;
padding: 8px;
}
.peers a {
......@@ -258,9 +275,13 @@ button.selected {
border: none;
cursor: pointer;
border-radius: 4px;
width: 78px;
height: 36px;
white-space: nowrap;
overflow: hidden;
}
#pen-tool {
.selectable-tool {
background-color: #2f2f2f;
color: white;
padding: 10px;
......@@ -268,27 +289,89 @@ button.selected {
border: none;
cursor: pointer;
border-radius: 50%;
margin-right: 8px;
}
#pen-tool:hover {
.selectable-tool:hover {
background-color: #4f4f4f !important;
transition-duration: 0.4s;
}
#pen-tool {
width: 39px;
height: 39px;
margin-right: 8px;
}
#pen-tool > i {
padding: 0 1.5px;
}
#eraser-tool {
background-color: #2f2f2f;
color: white;
padding: 10px;
font-size: 16px;
border: none;
cursor: pointer;
border-radius: 50%;
width: 39px;
height: 39px;
margin-right: 8px;
}
#eraser-tool:hover {
background-color: #4f4f4f !important;
transition-duration: 0.4s;
#eraser-tool > i {
padding: 0 1.5px;
}
#dragging-tool {
width: 39px;
height: 39px;
margin-right: 8px;
}
#dragging-tool > i {
padding: 0 2.5px;
}
#canvas-center {
width: 39px;
height: 39px;
margin-right: 8px;
}
#canvas-center > i {
padding: 0 1.5px;
}
#recognition-mode {
width: 39px;
height: 39px;
margin-right: 8px;
}
#recognition-mode > i {
padding: 0 2.5px;
}
#undo-tool {
width: 39px;
height: 39px;
margin-right: 8px;
}
#undo-tool.disabled {
display: none;
}
#undo-tool > i {
padding: 0 2.5px;
}
#fast-undo-tool {
width: 39px;
height: 39px;
margin-right: 8px;
}
#fast-undo-tool.disabled {
display: none;
}
#fast-undo-tool > i {
padding: 0 1.5px;
}
.properties {
......@@ -527,3 +610,32 @@ button.selected {
url("./assets/fonts/martel-v4-latin/martel-v4-latin-regular.svg#Martel")
format("svg");
}
.avatar {
margin-right: 5px;
}
#user-avatar {
color: white;
display: flex;
align-items: center;
background-color: #4f4f4fb7;
border-radius: 4px;
margin-left: 0.75em;
padding: 0 0.75em 0 0;
}
#status-info {
display: flex;
align-items: center;
justify-content: right;
}
#imperial-logo {
background-color: white;
display: flex;
align-items: center;
border-radius: 4px;
margin-left: 0.75em;
padding: 0;
}
File added