Skip to content
Snippets Groups Projects
Commit 663d7e42 authored by Jonas Zohren's avatar Jonas Zohren :speech_balloon:
Browse files

Initial commit

parents
No related branches found
No related tags found
No related merge requests found
/node_modules/
/public/build/
.DS_Store
{
"recommendations": ["svelte.svelte-vscode"]
}
README.md 0 → 100644
*Looking for a shareable component template? Go here --> [sveltejs/component-template](https://github.com/sveltejs/component-template)*
---
# svelte app
This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template.
To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit):
```bash
npx degit sveltejs/template svelte-app
cd svelte-app
```
*Note that you will need to have [Node.js](https://nodejs.org) installed.*
## Get started
Install the dependencies...
```bash
cd svelte-app
npm install
```
...then start [Rollup](https://rollupjs.org):
```bash
npm run dev
```
Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes.
By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`.
If you're using [Visual Studio Code](https://code.visualstudio.com/) we recommend installing the official extension [Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). If you are using other editors you may need to install a plugin in order to get syntax highlighting and intellisense.
## Building and running in production mode
To create an optimised version of the app:
```bash
npm run build
```
You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com).
## Single-page app mode
By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere.
If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json:
```js
"start": "sirv public --single"
```
## Using TypeScript
This template comes with a script to set up a TypeScript development environment, you can run it immediately after cloning the template with:
```bash
node scripts/setupTypeScript.js
```
Or remove the script via:
```bash
rm scripts/setupTypeScript.js
```
## Deploying to the web
### With [Vercel](https://vercel.com)
Install `vercel` if you haven't already:
```bash
npm install -g vercel
```
Then, from within your project folder:
```bash
cd public
vercel deploy --name my-project
```
### With [surge](https://surge.sh/)
Install `surge` if you haven't already:
```bash
npm install -g surge
```
Then, from within your project folder:
```bash
npm run build
surge public my-project.surge.sh
```
This diff is collapsed.
{
"name": "svelte-app",
"version": "1.0.0",
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w",
"start": "sirv public",
"validate": "svelte-check",
"test": "./node_modules/.bin/mocha --require ts-node/register ./src/test/*.spec.ts"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-node-resolve": "^11.0.0",
"@rollup/plugin-typescript": "^8.0.0",
"@tsconfig/svelte": "^1.0.0",
"@types/chai": "^4.2.15",
"@types/mocha": "^8.2.1",
"@types/node": "^14.14.31",
"chai": "^4.3.0",
"mocha": "^8.3.0",
"prettier": "^2.2.1",
"rollup": "^2.3.4",
"rollup-plugin-css-only": "^3.1.0",
"rollup-plugin-livereload": "^2.0.0",
"rollup-plugin-svelte": "^7.0.0",
"rollup-plugin-terser": "^7.0.0",
"svelte": "^3.0.0",
"svelte-check": "^1.0.0",
"svelte-preprocess": "^4.0.0",
"ts-node": "^9.1.1",
"tslib": "^2.0.0",
"typescript": "^4.0.0"
},
"dependencies": {
"sirv-cli": "^1.0.0"
}
}
public/favicon.png

3.05 KiB

.tg {
border-collapse: collapse;
border-spacing: 0;
}
.tg td {
border-color: black;
border-style: solid;
border-width: 1px;
font-family: Arial, sans-serif;
font-size: 14px;
overflow: hidden;
padding: 10px 5px;
word-break: normal;
}
.tg th {
border-color: black;
border-style: solid;
border-width: 1px;
font-family: Arial, sans-serif;
font-size: 14px;
font-weight: normal;
overflow: hidden;
padding: 10px 5px;
word-break: normal;
}
.tg .tg-0lax {
text-align: left;
vertical-align: top;
}
input {
width: 6rem;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<title>Svelte app</title>
<link rel='icon' type='image/png' href='/favicon.png'>
<link rel='stylesheet' href='/global.css'>
<link rel='stylesheet' href='/build/bundle.css'>
<script defer src='/build/bundle.js'></script>
</head>
<body>
</body>
</html>
import svelte from 'rollup-plugin-svelte';
import commonjs from '@rollup/plugin-commonjs';
import resolve from '@rollup/plugin-node-resolve';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
import sveltePreprocess from 'svelte-preprocess';
import typescript from '@rollup/plugin-typescript';
import css from 'rollup-plugin-css-only';
const production = !process.env.ROLLUP_WATCH;
function serve() {
let server;
function toExit() {
if (server) server.kill(0);
}
return {
writeBundle() {
if (server) return;
server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true
});
process.on('SIGTERM', toExit);
process.on('exit', toExit);
}
};
}
export default {
input: 'src/main.ts',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'public/build/bundle.js'
},
plugins: [
svelte({
preprocess: sveltePreprocess({ sourceMap: !production }),
compilerOptions: {
// enable run-time checks when not in production
dev: !production
}
}),
// we'll extract any component CSS out into
// a separate file - better for performance
css({ output: 'bundle.css' }),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration -
// consult the documentation for details:
// https://github.com/rollup/plugins/tree/master/packages/commonjs
resolve({
browser: true,
dedupe: ['svelte']
}),
commonjs(),
typescript({
sourceMap: !production,
inlineSources: !production
}),
// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),
// Watch the `public` directory and refresh the
// browser on changes when not in production
!production && livereload('public'),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser()
],
watch: {
clearScreen: false
}
};
<script lang="ts">
import type { WorkPackage } from "./estimator";
import RowWorkItem from "./RowWorkItem.svelte";
import SumRow from "./SumRow.svelte";
const NUMBER_OF_WORKPACKAGES = 10;
let workPackages: WorkPackage[] = []
for (let i = 0; i <= NUMBER_OF_WORKPACKAGES; i++) {
workPackages.push({a: null, b:null, c: null});
}
$: dataJson = JSON.stringify(workPackages, null, 2)
</script>
<main>
<table class="tg">
<thead>
<th class="tg-0lax">a</th>
<th class="tg-0lax">c</th>
<th class="tg-0lax">b</th>
<th class="tg-0lax">E</th>
<th class="tg-0lax">S</th>
<th class="tg-0lax">S/E</th>
<th class="tg-0lax">V</th>
</thead>
<tbody>
{#each workPackages as workPackage, i (i)}
<RowWorkItem bind:a={workPackage.a} bind:b={workPackage.b} bind:c={workPackage.c}></RowWorkItem>
{/each}
<SumRow {workPackages}></SumRow>
</tbody>
</table>
<pre>
{dataJson}
</pre>
</main>
<script lang="ts">
import { calculateE, calculateS, calculateV } from "./estimator";
import { roundOne } from "./utils";
export let a: number
export let b: number
export let c: number;
$: E = ( typeof a !== "number" || typeof b !== "number") ? null : calculateE({a,b,c})
$: S = ( typeof a !== "number" || typeof b !== "number") ? null : calculateS({a,b,c})
$: V = ( typeof a !== "number" || typeof b !== "number") ? null : calculateV({a,b,c})
$: SEPercent = (typeof S !== 'number' || typeof E !== 'number') ? null : (S/E)*100
function hideNull(input: any|null): string {
return input === null ? "-" : ""+input;
}
</script>
<tr>
<td class="tg-0lax">
<input type="number" class="a-input" bind:value="{a}">
</td>
<td class="tg-0lax">
<input type="number" class="c-input" bind:value="{c}">
</td>
<td class="tg-0lax">
<input type="number" class="c-input" bind:value="{b}">
</td>
<td class="tg-0lax">{hideNull(roundOne(E))}</td>
<td class="tg-0lax">{hideNull(roundOne(S))}</td>
<td class="tg-0lax">{hideNull(roundOne(SEPercent))}%</td>
<td class="tg-0lax">{hideNull(roundOne(V))}</td>
</tr>
\ No newline at end of file
<script lang="ts">
import type { WorkPackage } from "./estimator";
import { calculateSSum, calculateESum } from './estimator';
import { roundOne, sumIgnoreNonNumbers } from "./utils";
export let workPackages: WorkPackage[]
</script>
<tr>
<td class="tg-0lax">
{sumIgnoreNonNumbers(workPackages.map(workPackage => workPackage.a))}
</td>
<td class="tg-0lax">
{sumIgnoreNonNumbers(workPackages.map(workPackage => workPackage.c))}
</td>
<td class="tg-0lax">
{sumIgnoreNonNumbers(workPackages.map(workPackage => workPackage.b))}
</td>
<td class="tg-0lax">
{roundOne(calculateESum(workPackages))}
</td>
<td class="tg-0lax">
{roundOne(calculateSSum(workPackages))}
</td>
<td class="tg-0lax">
</td>
<td class="tg-0lax">
</td>
</tr>
\ No newline at end of file
import { sumIgnoreNonNumbers } from "./utils";
export interface WorkPackage {
/** Lower bound of effort needed to complete workPackage */
a: number;
/** Upper bound of effort needed to complete workPackage */
b: number;
/** Average expected effort needed to complete workPackage */
c?: number;
}
/**
* Calculate the expected effort for a given workpackage
*/
export function calculateE(workPackage: WorkPackage): number {
const { a, b, c } = workPackage;
if (
typeof a !== "number" ||
a === null ||
typeof b !== "number" ||
b === null
) {
throw new TypeError("@calculateE(): At least a and b must be numbers");
}
return typeof c !== "number" || c === null
? (a + b) / 2
: (a + 4 * c + b) / 6;
}
export function calculateV(workPackage: WorkPackage): number {
const { a, b } = workPackage;
if (typeof a !== "number" || typeof b !== "number") {
throw new TypeError("@calculateV(): a and b must be numbers");
}
return ((b - a) * (b - a)) / 36;
}
export function calculateS(workPackage: WorkPackage): number {
const { a, b } = workPackage;
if (typeof a !== "number" || typeof b !== "number") {
throw new TypeError("@calculateS(): a and b must be numbers");
}
return (b - a) / 6;
}
export function calculateSSum(workPackages: WorkPackage[]): number {
return Math.sqrt(
sumIgnoreNonNumbers(
workPackages
.filter(({ a, b }) => typeof a === "number" && typeof b === "number")
.map((workPackage) => calculateS(workPackage))
)
);
}
export function calculateESum(workPackages: WorkPackage[]): number {
return sumIgnoreNonNumbers(
workPackages
.filter(({ a, b }) => typeof a === "number" && typeof b === "number")
.map((workPackage) => calculateE(workPackage))
);
}
import App from './App.svelte';
const app = new App({
target: document.body,
props: {
name: 'world'
}
});
export default app;
\ No newline at end of file
import { WorkPackage, calculateE, calculateV, calculateS } from "../estimator";
import "mocha";
import { assert } from "chai";
const roundOne = (n) => Math.round(n * Math.pow(10, 1)) / Math.pow(10, 1);
describe("Estimator Calculation", function () {
describe("#calculateE()", function () {
it("should return 100, if a and b are 100 and c undefined", function () {
assert.equal(calculateE({ a: 100, b: 100 }), 100);
});
it("should return 100, if a and b are 100 and c null", function () {
assert.equal(calculateE({ a: 100, b: 100, c: null }), 100);
});
it("should return 50, if a = 0, b = 100 and c null", function () {
assert.equal(calculateE({ a: 0, b: 100, c: null }), 50);
});
it("should return 50, if a = 0, b = 100 and c = 50", function () {
assert.equal(calculateE({ a: 0, b: 100, c: 50 }), 50);
});
describe("Vorlesungsbeispiele:", function () {
it("should return 36.7, if {a,c,b} = {20,30,80}", function () {
assert.equal(roundOne(calculateE({ a: 20, c: 30, b: 80 })), 36.7);
});
it("should return 20, if {a,c,b} = {10,20,30}", function () {
assert.equal(roundOne(calculateE({ a: 10, c: 20, b: 30 })), 20);
});
it("should return 20.8, if {a,c,b} = {15,20,30}", function () {
assert.equal(roundOne(calculateE({ a: 15, c: 20, b: 30 })), 20.8);
});
it("should return 9.5, if {a,c,b} = {5,8,20}", function () {
assert.equal(roundOne(calculateE({ a: 5, c: 8, b: 20 })), 9.5);
});
});
});
describe("#calculateV()", function () {
describe("Vorlesungsbeispiele:", function () {
it("should return 36.7, if {a,c,b} = {20,30,80}", function () {
assert.equal(roundOne(calculateE({ a: 20, c: 30, b: 80 })), 36.7);
});
it("should return 11.1, if {a,c,b} = {10,20,30}", function () {
assert.equal(roundOne(calculateV({ a: 10, c: 20, b: 30 })), 11.1);
});
it("should return 6.3, if {a,c,b} = {15,20,30}", function () {
assert.equal(roundOne(calculateV({ a: 15, c: 20, b: 30 })), 6.3);
});
it("should return 6.3, if {a,c,b} = {5,8,20}", function () {
assert.equal(roundOne(calculateV({ a: 5, c: 8, b: 20 })), 6.3);
});
});
});
describe("#calculateS()", function () {
describe("Vorlesungsbeispiele:", function () {
it("should return 10, if {a,c,b} = {20,30,80}", function () {
assert.equal(roundOne(calculateS({ a: 20, c: 30, b: 80 })), 10);
});
it("should return 3.3, if {a,c,b} = {10,20,30}", function () {
assert.equal(roundOne(calculateS({ a: 10, c: 20, b: 30 })), 3.3);
});
it("should return 2.5, if {a,c,b} = {15,20,30}", function () {
assert.equal(roundOne(calculateS({ a: 15, c: 20, b: 30 })), 2.5);
});
it("should return 2.5, if {a,c,b} = {5,8,20}", function () {
assert.equal(roundOne(calculateS({ a: 5, c: 8, b: 20 })), 2.5);
});
});
});
});
/**
* Rounds a number to one digit after the period dot or null, if the input is not a number
* @param n number to round
*/
export function roundOne(n: number): number | null {
if (typeof n === "number" && !isNaN(n)) {
return Math.round(n * Math.pow(10, 1)) / Math.pow(10, 1);
} else {
return null;
}
}
export function sumIgnoreNonNumbers(values: number[]): number {
return values
.filter((n) => typeof n === "number")
.reduce((acc, curr) => acc + curr, 0);
}
{
"extends": "@tsconfig/svelte/tsconfig.json",
"compilerOptions": {
"types": ["mocha"]
},
"include": ["src/**/*"],
"exclude": ["node_modules/*", "__sapper__/*", "public/*"]
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment