├── public ├── robots.txt ├── favicon.ico ├── img │ └── icons │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon-96x96.png │ │ ├── mstile-150x150.png │ │ ├── apple-touch-icon.png │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon-57x57.png │ │ ├── apple-touch-icon-60x60.png │ │ ├── apple-touch-icon-72x72.png │ │ ├── apple-touch-icon-76x76.png │ │ ├── apple-touch-icon-114x114.png │ │ ├── apple-touch-icon-120x120.png │ │ ├── apple-touch-icon-144x144.png │ │ ├── apple-touch-icon-152x152.png │ │ ├── apple-touch-icon-180x180.png │ │ ├── msapplication-icon-144x144.png │ │ ├── android-chrome-maskable-192x192.png │ │ ├── android-chrome-maskable-512x512.png │ │ └── safari-pinned-tab.svg └── index.html ├── .browserslistrc ├── src ├── assets │ └── logo.png ├── main.js ├── registerServiceWorker.js ├── App.vue └── utils.js ├── babel.config.js ├── coin.code-workspace ├── .gitignore ├── vue.config.js ├── README.md ├── .eslintrc.js └── package.json /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/public/favicon.ico -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/src/assets/logo.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /coin.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": {} 8 | } -------------------------------------------------------------------------------- /public/img/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/public/img/icons/favicon-16x16.png -------------------------------------------------------------------------------- /public/img/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/public/img/icons/favicon-32x32.png -------------------------------------------------------------------------------- /public/img/icons/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/public/img/icons/favicon-96x96.png -------------------------------------------------------------------------------- /public/img/icons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/public/img/icons/mstile-150x150.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/public/img/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /public/img/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/public/img/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/img/icons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/public/img/icons/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/public/img/icons/apple-touch-icon-57x57.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/public/img/icons/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/public/img/icons/apple-touch-icon-72x72.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/public/img/icons/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/public/img/icons/apple-touch-icon-114x114.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/public/img/icons/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/public/img/icons/apple-touch-icon-144x144.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/public/img/icons/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/public/img/icons/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /public/img/icons/msapplication-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/public/img/icons/msapplication-icon-144x144.png -------------------------------------------------------------------------------- /public/img/icons/android-chrome-maskable-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/public/img/icons/android-chrome-maskable-192x192.png -------------------------------------------------------------------------------- /public/img/icons/android-chrome-maskable-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidacm/fscoin/main/public/img/icons/android-chrome-maskable-512x512.png -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import './registerServiceWorker' 4 | 5 | new Vue({ 6 | render: h => h(App), 7 | }).$mount('#app') 8 | -------------------------------------------------------------------------------- /public/img/icons/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | publicPath: process.env.NODE_ENV === 'production' 3 | ? '/fscoin/' 4 | : '/', 5 | pwa: { 6 | name: "FSCoin", 7 | themeColor: "#4DBA87", 8 | msTileColor: "#000000", 9 | appleMobileWebAppCapable: "yes", 10 | appleMobileWebAppStatusBarStyle: "black", 11 | // configure the workbox plugin 12 | workboxPluginMode: "GenerateSW", 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fsCoin 2 | 3 | ## Project setup 4 | ``` 5 | npm install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | npm run serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | npm run build 16 | ``` 17 | 18 | ### Lints and fixes files 19 | ``` 20 | npm run lint 21 | ``` 22 | 23 | ### Customize configuration 24 | See [Configuration Reference](https://cli.vuejs.org/config/). 25 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | 'extends': [ 7 | 'plugin:vue/essential', 8 | 'eslint:recommended' 9 | ], 10 | parserOptions: { 11 | parser: 'babel-eslint' 12 | }, 13 | rules: { 14 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 15 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off' 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "FSCoin", 3 | "homepage": "https://github.com/davidacm/fscoin", 4 | "version": "0.1.0", 5 | "private": true, 6 | "scripts": { 7 | "serve": "vue-cli-service serve", 8 | "build": "vue-cli-service build", 9 | "lint": "vue-cli-service lint", 10 | "deploy": "node ./node_modules/vue-gh-pages/index.js -b gh-pages" 11 | }, 12 | "dependencies": { 13 | "bulma": "^0.9.3", 14 | "core-js": "^3.6.5", 15 | "register-service-worker": "^1.7.1", 16 | "vue": "^2.6.11" 17 | }, 18 | "devDependencies": { 19 | "@vue/cli-plugin-babel": "~4.5.0", 20 | "@vue/cli-plugin-eslint": "~4.5.0", 21 | "@vue/cli-plugin-pwa": "~4.5.0", 22 | "@vue/cli-service": "~4.5.0", 23 | "babel-eslint": "^10.1.0", 24 | "eslint": "^6.7.2", 25 | "eslint-plugin-vue": "^6.2.2", 26 | "vue-gh-pages": "^1.19.1", 27 | "vue-template-compiler": "^2.6.11" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/registerServiceWorker.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { register } from 'register-service-worker' 4 | 5 | if (process.env.NODE_ENV === 'production') { 6 | register(`${process.env.BASE_URL}service-worker.js`, { 7 | ready () { 8 | console.log( 9 | 'App is being served from cache by a service worker.\n' + 10 | 'For more details, visit https://goo.gl/AFskqB' 11 | ) 12 | }, 13 | registered () { 14 | console.log('Service worker has been registered.') 15 | }, 16 | cached () { 17 | console.log('Content has been cached for offline use.') 18 | }, 19 | updatefound () { 20 | console.log('New content is downloading.') 21 | }, 22 | updated () { 23 | console.log('New content is available; please refresh.') 24 | }, 25 | offline () { 26 | console.log('No internet connection found. App is running in offline mode.') 27 | }, 28 | error (error) { 29 | console.error('Error during service worker registration:', error) 30 | } 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 51 | 52 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | export const tLocal = { 2 | /** 3 | * get the value from the local storage. The value will be parsed before return. 4 | * the default value, if given, won't be parsed. 5 | * @param key: the key to get from the local storage. 6 | * @param defaultValue: an optional value to be returned if the key is not found. 7 | * @returns: the value of the key if exist. Default value or null otherwise. 8 | */ 9 | get(key, defaultValue) { 10 | let v = localStorage.getItem(key); 11 | return v !== null ? JSON.parse(v) : defaultValue ? defaultValue : v; 12 | }, 13 | /** 14 | * 15 | * @param key: the key to asign the value. 16 | * @param value: an object to store. JSON.stringify will be aplied to this object. 17 | * @returns: true if all is OK. 18 | */ 19 | set(key, value) { 20 | localStorage.setItem(key, JSON.stringify(value)); 21 | return true; 22 | }, 23 | remove(key) { 24 | localStorage.removeItem(key); 25 | } 26 | }; 27 | 28 | // generates an unique id (consecutive number) to use as a ID. Just a temporal solution to do some tests. 29 | export const uuid = { 30 | counter: 0, 31 | // tLocal.get('count', 0) as number, 32 | getId() { 33 | // tLocal.set("count", ++this.counter) 34 | ++this.counter; 35 | return String(this.counter); 36 | } 37 | }; 38 | 39 | const beepState = { 40 | audioContext: undefined, 41 | osc: undefined, 42 | waitToBreak: 0, 43 | isRunning: false 44 | }; 45 | 46 | function startAudioContext() { 47 | if (!beepState.audioContext) 48 | beepState.audioContext = new AudioContext(); 49 | } 50 | 51 | /** 52 | * produces a beep tone with a sine wave in the browser. 53 | * @param frequency: the freq of the wave. default 440. 54 | * @param duration: duration in ms. default is 100. 55 | * @param volume: the volume, default is 1. Don't use very high values or you can get distorted sounds. 56 | */ 57 | export function beep(frequency = 440, duration = 100, volume = 1) { 58 | var _a; 59 | startAudioContext(); 60 | if (!beepState.audioContext) 61 | return; 62 | if (beepState.osc) 63 | beepState.osc.stop(beepState.audioContext.currentTime); 64 | beepState.osc = (_a = beepState.audioContext) === null || _a === void 0 ? void 0 : _a.createOscillator(); 65 | let [osc, audio] = [beepState.osc, beepState.audioContext]; 66 | let g = audio.createGain(); 67 | osc.connect(g); 68 | osc.frequency.value = frequency; 69 | osc.type = "sine"; 70 | g.connect(audio.destination); 71 | g.gain.value = volume; 72 | osc.start(audio.currentTime); 73 | beepState.isRunning = true; 74 | osc.stop(audio.currentTime + duration * 0.001); 75 | osc.onended = () => beepState.isRunning = false; 76 | } 77 | 78 | const WAIT_TIME = 30; 79 | /** 80 | * for debug purposes. If a beep is running, this will wait WAIT_TIME ms more from the last beep to interrupt the current beep. This will allow to hear the differences between events. 81 | * WAIT_TIME is set to 30 ms, change it to your needs. 82 | * */ 83 | export function beepSlower(frequency = 440, duration = 100, volume = 1) { 84 | if (beepState.waitToBreak < 0) 85 | beepState.waitToBreak = 0; 86 | if (beepState.isRunning) { 87 | beepState.waitToBreak += WAIT_TIME; 88 | setTimeout(() => { 89 | beep(frequency, duration, volume); 90 | beepState.waitToBreak -= WAIT_TIME; 91 | }, beepState.waitToBreak); 92 | } 93 | else 94 | beep(frequency, duration, volume); 95 | } 96 | 97 | const ARRAY_CREATORS = { 98 | 8: Uint8Array, 99 | 16: Uint16Array, 100 | 32: Uint32Array 101 | }; 102 | 103 | export function randomIntegers(start, end, quant) { 104 | if (start > end) { 105 | [start, end] = [end, start]; 106 | } 107 | const totalRange = end - start + 1; 108 | const nBytes = Math.ceil(Math.log(totalRange) / Math.LN2); 109 | let bytes = -1; 110 | for (let k in ARRAY_CREATORS) { 111 | if (parseInt(k) - nBytes >= 0) { 112 | bytes = parseInt(k); 113 | break; 114 | } 115 | } 116 | if (!(bytes in ARRAY_CREATORS)) 117 | throw Error("Unable to get the correct bytes for the required random range"); 118 | const tmp = new ARRAY_CREATORS[bytes](quant); 119 | window.crypto.getRandomValues(tmp); 120 | const maxRange = Math.pow(2, bytes) - 1; 121 | return tmp.map(n => totalRange / maxRange * n + start); 122 | } 123 | 124 | 125 | export function randint(start, end) { 126 | return randomIntegers(start, end, 1)[0]; 127 | } 128 | 129 | export function choose() { 130 | const l = randint(1, 1023); 131 | const a = {0:0, 1:0}; 132 | for (let i = 0; i<= l; ++i) 133 | a[randint(1, 1000)%2] += 1; 134 | return a[1] > a[0]? 1: 0; 135 | } 136 | 137 | export function beepChoose() { 138 | function timeoutChoose() { 139 | const c = choose(); 140 | let fq = c == 1? 1500: 500; 141 | beepSlower(fq, 50); 142 | } 143 | 144 | for (let i = 0; i<3; ++i) { 145 | setTimeout(timeoutChoose, i*1000 + randint(1, 1023)); 146 | } 147 | } 148 | --------------------------------------------------------------------------------