From 0949e231990ab26ea1d4b19abfec2c6d273c38db Mon Sep 17 00:00:00 2001 From: Simon Marsh Date: Fri, 31 Mar 2023 17:00:53 +0100 Subject: [PATCH] final beta --- README.md | 7 +- index.html | 12 ++- package.json | 3 + public/dn42.svg | 30 +++++++ public/favicon.ico | Bin 0 -> 318 bytes public/vite.svg | 1 - src/App.vue | 30 ------- src/Clicker42.vue | 63 ++++++++++++++ src/assets/vue.svg | 1 - src/clicker42.js | 20 +++++ src/components/BWInfo.vue | 27 ++++++ src/components/BWPanel.vue | 14 +++ src/components/Buyer.vue | 32 +++++++ src/components/Elapsed.vue | 36 ++++++++ src/components/HelloWorld.vue | 40 --------- src/components/LevelInfo.vue | 53 ++++++++++++ src/components/LevelPanel.vue | 23 +++++ src/components/LevelSelector.vue | 44 ++++++++++ src/components/ServicesPanel.vue | 57 +++++++++++++ src/components/SettingsPanel.vue | 21 +++++ src/components/UpgradeBuyer.vue | 25 ++++++ src/components/UpgradeIcon.vue | 12 +++ src/main.js | 5 -- src/model/autobuyer.js | 42 +++++++++ src/model/bandwidth.js | 81 ++++++++++++++++++ src/model/leveldefs.js | 89 +++++++++++++++++++ src/model/levels.js | 141 +++++++++++++++++++++++++++++++ src/model/numbers.js | 43 ++++++++++ src/model/services.js | 90 ++++++++++++++++++++ src/model/state.js | 133 +++++++++++++++++++++++++++++ src/style.css | 89 ------------------- yarn.lock | 28 ++++++ 32 files changed, 1117 insertions(+), 175 deletions(-) create mode 100644 public/dn42.svg create mode 100644 public/favicon.ico delete mode 100644 public/vite.svg delete mode 100644 src/App.vue create mode 100644 src/Clicker42.vue delete mode 100644 src/assets/vue.svg create mode 100644 src/clicker42.js create mode 100644 src/components/BWInfo.vue create mode 100644 src/components/BWPanel.vue create mode 100644 src/components/Buyer.vue create mode 100644 src/components/Elapsed.vue delete mode 100644 src/components/HelloWorld.vue create mode 100644 src/components/LevelInfo.vue create mode 100644 src/components/LevelPanel.vue create mode 100644 src/components/LevelSelector.vue create mode 100644 src/components/ServicesPanel.vue create mode 100644 src/components/SettingsPanel.vue create mode 100644 src/components/UpgradeBuyer.vue create mode 100644 src/components/UpgradeIcon.vue delete mode 100644 src/main.js create mode 100644 src/model/autobuyer.js create mode 100644 src/model/bandwidth.js create mode 100644 src/model/leveldefs.js create mode 100644 src/model/levels.js create mode 100644 src/model/numbers.js create mode 100644 src/model/services.js create mode 100644 src/model/state.js delete mode 100644 src/style.css diff --git a/README.md b/README.md index e62e093..7668b8c 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,4 @@ -# Vue 3 + Vite +# Clicker42 -This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 ` + +
+ diff --git a/package.json b/package.json index 8a9e0be..140052c 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,9 @@ "preview": "vite preview" }, "dependencies": { + "bootstrap": "^5.2.3", + "bootstrap-icons": "^1.10.3", + "pinia": "^2.0.33", "vue": "^3.2.47" }, "devDependencies": { diff --git a/public/dn42.svg b/public/dn42.svg new file mode 100644 index 0000000..f00ec76 --- /dev/null +++ b/public/dn42.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..2e004d6c6c37cc0a5e8209703f81784b0923a639 GIT binary patch literal 318 zcmb79F%E+;5HnIAkOPS|EeouO2k?UYiHRw{>cmUBc4cYmyXZy+9NCV~iIe~hR|tXn zz|;UefQby`lhnClGp(YXBBf-Wb4HBO_IE@s(aqAn*e;6<1HGGJS@=-B#H^;h!L#=w gwXf}!mI64>5Ab~h#|Z5F%CR!DKj}Z_Lie-oe}gP1JOBUy literal 0 HcmV?d00001 diff --git a/public/vite.svg b/public/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/App.vue b/src/App.vue deleted file mode 100644 index 341dbf0..0000000 --- a/src/App.vue +++ /dev/null @@ -1,30 +0,0 @@ - - - - - diff --git a/src/Clicker42.vue b/src/Clicker42.vue new file mode 100644 index 0000000..57a7507 --- /dev/null +++ b/src/Clicker42.vue @@ -0,0 +1,63 @@ + + + + diff --git a/src/assets/vue.svg b/src/assets/vue.svg deleted file mode 100644 index 770e9d3..0000000 --- a/src/assets/vue.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/clicker42.js b/src/clicker42.js new file mode 100644 index 0000000..6c1b799 --- /dev/null +++ b/src/clicker42.js @@ -0,0 +1,20 @@ +///////////////////////////////////////////////////////////////////////// + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import 'bootstrap/dist/css/bootstrap.css' +import 'bootstrap-icons/font/bootstrap-icons.css' +import Clicker42 from './Clicker42.vue' + +///////////////////////////////////////////////////////////////////////// + +const pinia = createPinia() +const clicker = createApp(Clicker42) + +///////////////////////////////////////////////////////////////////////// + +clicker.use(pinia) +clicker.mount('#clicker42') + +///////////////////////////////////////////////////////////////////////// +// end of file \ No newline at end of file diff --git a/src/components/BWInfo.vue b/src/components/BWInfo.vue new file mode 100644 index 0000000..f059996 --- /dev/null +++ b/src/components/BWInfo.vue @@ -0,0 +1,27 @@ + + + diff --git a/src/components/BWPanel.vue b/src/components/BWPanel.vue new file mode 100644 index 0000000..afe8bac --- /dev/null +++ b/src/components/BWPanel.vue @@ -0,0 +1,14 @@ + + + diff --git a/src/components/Buyer.vue b/src/components/Buyer.vue new file mode 100644 index 0000000..fd3442c --- /dev/null +++ b/src/components/Buyer.vue @@ -0,0 +1,32 @@ + + + diff --git a/src/components/Elapsed.vue b/src/components/Elapsed.vue new file mode 100644 index 0000000..6ac6105 --- /dev/null +++ b/src/components/Elapsed.vue @@ -0,0 +1,36 @@ + + + diff --git a/src/components/HelloWorld.vue b/src/components/HelloWorld.vue deleted file mode 100644 index f5e4f53..0000000 --- a/src/components/HelloWorld.vue +++ /dev/null @@ -1,40 +0,0 @@ - - - - - diff --git a/src/components/LevelInfo.vue b/src/components/LevelInfo.vue new file mode 100644 index 0000000..46101a4 --- /dev/null +++ b/src/components/LevelInfo.vue @@ -0,0 +1,53 @@ + + + + diff --git a/src/components/LevelPanel.vue b/src/components/LevelPanel.vue new file mode 100644 index 0000000..0539788 --- /dev/null +++ b/src/components/LevelPanel.vue @@ -0,0 +1,23 @@ + + + diff --git a/src/components/LevelSelector.vue b/src/components/LevelSelector.vue new file mode 100644 index 0000000..029aa1f --- /dev/null +++ b/src/components/LevelSelector.vue @@ -0,0 +1,44 @@ + + + + diff --git a/src/components/ServicesPanel.vue b/src/components/ServicesPanel.vue new file mode 100644 index 0000000..ac94ff0 --- /dev/null +++ b/src/components/ServicesPanel.vue @@ -0,0 +1,57 @@ + + + diff --git a/src/components/SettingsPanel.vue b/src/components/SettingsPanel.vue new file mode 100644 index 0000000..dd915f0 --- /dev/null +++ b/src/components/SettingsPanel.vue @@ -0,0 +1,21 @@ + + + diff --git a/src/components/UpgradeBuyer.vue b/src/components/UpgradeBuyer.vue new file mode 100644 index 0000000..ad71c35 --- /dev/null +++ b/src/components/UpgradeBuyer.vue @@ -0,0 +1,25 @@ + + + diff --git a/src/components/UpgradeIcon.vue b/src/components/UpgradeIcon.vue new file mode 100644 index 0000000..68dc9c6 --- /dev/null +++ b/src/components/UpgradeIcon.vue @@ -0,0 +1,12 @@ + + + diff --git a/src/main.js b/src/main.js deleted file mode 100644 index 2425c0f..0000000 --- a/src/main.js +++ /dev/null @@ -1,5 +0,0 @@ -import { createApp } from 'vue' -import './style.css' -import App from './App.vue' - -createApp(App).mount('#app') diff --git a/src/model/autobuyer.js b/src/model/autobuyer.js new file mode 100644 index 0000000..a9fb1f6 --- /dev/null +++ b/src/model/autobuyer.js @@ -0,0 +1,42 @@ +///////////////////////////////////////////////////////////////////////// +// level functions + +export class Autobuyer { + constructor() { + this.levels = false + this.bandwidth = false + } + + // save data + save() { + return { + levels: this.levels, + bandwidth: this.bandwidth + } + } + + restore(save_data) { + Object.assign(this, save_data) + } + + // timer tick + tick(state, interval) { + + if (this.levels) { + state.levels.forEach(l => { + if (l.shouldAutobuy()) { l.upgradeMultiplier() } + }); + } + + if (this.bandwidth) { + + if (state.bandwidth.canUpgrade(state)) { + state.bandwidth.upgrade(state) + } + } + } + +} + +///////////////////////////////////////////////////////////////////////// +// end of file \ No newline at end of file diff --git a/src/model/bandwidth.js b/src/model/bandwidth.js new file mode 100644 index 0000000..9e57823 --- /dev/null +++ b/src/model/bandwidth.js @@ -0,0 +1,81 @@ +///////////////////////////////////////////////////////////////////////// +// Bandwidth functions + +export class Bandwidth { + + constructor() { + this.count = BigInt(0) + this.rate = BigInt(1) + this.rateCost = BigInt(321) + } + + // save data + save() { + let save_data = {} + let props = [ + 'count', + 'rate', 'rateCost' + ] + + props.forEach((prop) => { + save_data[prop] = this[prop] + }) + return save_data + } + + restore(save_data) { + Object.assign(this, save_data) + } + + // handle upgrades + canUpgrade(state) { + return this.rateCost <= state.levels[0].count + } + + upgrade(state) { + // use up packets + state.levels[0].count -= this.rateCost + + // increase bandwidth rate and cost + if (this.rate < 10) { + this.rate += 1n + this.rateCost *= 2n + } + else { + this.rate *= 2n + this.rateCost += this.rateCost * this.rate + } + } + + serviceBonus(state) { + let bonus = 0n + + if (state.services.time.level > 0) { + let i + for(i = state.levels.length - 1; i >= 0; i--) { + if (state.levels[i].unlocked) { + let multiplier = state.ui.elapsed - state.levels[i].unlockTime + // multiplier = multiplier > 7200 ? 7200 : multiplier + bonus += (this.rate * BigInt(multiplier)) / BigInt(7200 / i) + break + } + } + if (state.services.time.level > 1) { + //let multiplier = state.ui.elapsed > 172800 ? 86400 : state.ui.elapsed + let multiplier = state.ui.elapsed + bonus += (this.rate * BigInt(multiplier)) / BigInt(86400/i) + } + } + + return bonus + } + + // regular updates + tick(state, interval) { + this.count += this.rate * interval + this.serviceBonus(state) + } + +} + +///////////////////////////////////////////////////////////////////////// +// end of file \ No newline at end of file diff --git a/src/model/leveldefs.js b/src/model/leveldefs.js new file mode 100644 index 0000000..6a29106 --- /dev/null +++ b/src/model/leveldefs.js @@ -0,0 +1,89 @@ +///////////////////////////////////////////////////////////////////////// + +import { LevelTemplate } from './levels.js' + +///////////////////////////////////////////////////////////////////////// + +export const LevelDefs = [ + new LevelTemplate({ + name: 'Newcomer', + blurb: "Your PR has been merged and it's time to start pushing packets.", + units: 'packets', + cost: BigInt(1), + unlocked: true + }), + + new LevelTemplate({ + name: 'Peering Pro', + blurb: 'Increase the number of peers to get more packets.', + units: 'peers', + cost: BigInt(10) + }), + + new LevelTemplate({ + name: 'IPv6 Rollout', + blurb: 'Rollout IPv6 across your network.', + units: 'link local addresses', + cost: BigInt(100) + }), + + new LevelTemplate({ + name: 'Routing Updates', + blurb: 'Optimise your bird config to get ROA filters (look, no-one said this should make sense).', + units: 'ROA filters', + cost: BigInt(1000) + }), + + new LevelTemplate({ + name: 'Node Operator', + blurb: 'Expand your global footprint with new nodes.', + units: 'low end vps', + cost: BigInt(10000) + }), + + new LevelTemplate({ + name: 'Security Guru', + blurb: 'Improve your security by implementing firewalls.', + units: 'firewalls', + cost: BigInt(100000) + }), + + new LevelTemplate({ + name: 'File Sharing', + blurb: 'Spread your packets around.', + units: 'files transferred', + cost: BigInt(1000000) + }), + + new LevelTemplate({ + name: 'Anycast Deployment', + blurb: 'Create resilient global services.', + units: 'paths', + cost: BigInt(10000000) + }), + + new LevelTemplate({ + name: 'Community Member', + blurb: 'Help others by contributing to the wiki.', + units: 'wiki edits', + cost: BigInt(100000000) + }), + + new LevelTemplate({ + name: 'Multicast Streamer', + blurb: 'Use up all your bandwidth streaming music and video.', + units: 'streams', + cost: BigInt(1000000000) + }), + + new LevelTemplate({ + name: 'DN42 Master', + blurb: 'The network must grow !', + units: 'rp_filters disabled', + cost: BigInt(10000000000) + }) + +] + +///////////////////////////////////////////////////////////////////////// +// end of file \ No newline at end of file diff --git a/src/model/levels.js b/src/model/levels.js new file mode 100644 index 0000000..ae08158 --- /dev/null +++ b/src/model/levels.js @@ -0,0 +1,141 @@ +///////////////////////////////////////////////////////////////////////// +// level functions + +export class LevelTemplate { + constructor(data) { + + // common variables + this.count = BigInt(0) + this.multiplier = BigInt(1) + this.multiplierCost = BigInt(10) + this.efficiency = BigInt(1) + this.efficiencyCost = BigInt(1) + this.unlocked = false + this.unlockTime = 0 + + // copy level specific data in to object + Object.assign(this, data) + } + + // save data + save() { + let save_data = { } + let props = [ + 'index', 'count', + 'multiplier', 'multiplierCost', + 'efficiency', 'efficiencyCost', + 'unlocked', 'unlockTime' + ] + + props.forEach((prop) => { + save_data[prop] = this[prop] + }) + return save_data + } + + restore(save_data) { + Object.assign(this, save_data) + } + + // unlock this level + unlock(elapsed) { + this.unlocked = true + this.unlockTime = elapsed + } + + // upgrade functions + canUpgrade() { + return this.count >= this.multiplierCost + } + + shouldAutobuy() { + return this.count >= (this.multiplierCost * 2n) + } + + upgradeMultiplier() { + this.count -= this.multiplierCost + this.multiplier *= 2n + this.multiplierCost *= 12n + } + + upgradeEfficiency(state) { + // am I the last level ? + if (this.index == (state.count - 1)) { return } + + let nextLevel = state.levels[this.index + 1] + nextLevel.count -= this.efficiencyCost + this.efficiency *= 2n + this.efficiencyCost *= 11n + } + + // calculate max unit cost as percentage of previous level units + calcUnitCostPercent(state) { + if (this.index == 0) { return 100 } + + let max = this.maxCanBuyInternal(state) + let units = state.levels[this.index - 1].count + if (units == 0) { return 100 } + return Number((max * this.cost * 100n) / units) + } + + // calculate max unit cost as percentage of available bandwidth + calcBWCostPercent(state) { + let max = this.maxCanBuyInternal(state) + let bw = state.bandwidth.count + if (bw == 0) { return 100 } + return Number((max * 100n) / bw) + } + + // unit purchasing + buy(state, amount) { + + // take cost based on amount less the efficiency + let a = amount / this.efficiency + state.bandwidth.count -= a + if (this.index != 0) { + state.levels[this.index - 1].count -= a * this.cost + } + + // increase units + this.count += amount + } + + // calculate the maximum number of units that can be bought + maxCanBuyInternal(state) { + let max + + if (this.index == 0) { + // level zero is limited by bandwidth only + max = state.bandwidth.count + + } else { + // otherwise its the maximum of bw and previous level + max = state.levels[this.index - 1].count / this.cost + if (max > state.bandwidth.count) { + max = state.bandwidth.count + } + } + return max + } + + maxCanBuy(state) { + return this.maxCanBuyInternal(state) * this.efficiency + } + + // timer tick + tick(state, interval) { + // am I the last level ? + if (this.index == (state.count - 1)) { return } + + // add units to this level + let nextLevel = state.levels[this.index + 1] + this.count += nextLevel.count * nextLevel.multiplier + + // unlock next level if possible + if ((this.count > 0) && (!nextLevel.unlocked)) { nextLevel.unlock(state.ui.elapsed) } + } + +} + +///////////////////////////////////////////////////////////////////////// +// end of file \ No newline at end of file diff --git a/src/model/numbers.js b/src/model/numbers.js new file mode 100644 index 0000000..0c4b865 --- /dev/null +++ b/src/model/numbers.js @@ -0,0 +1,43 @@ +///////////////////////////////////////////////////////////////////////// +// number functions + +const SISym = [ + '', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'R', 'Q' +] + +export function nstr(big) { + + let m = 0 + let r = 0 + const onek = BigInt(1000) + + while (big >= onek) { + r = Number(big % onek) + big /= onek + m++ + } + + // convert to fraction + let n = Number(big) + let f = n + (r / 1000) + + if (m == 0) { + // simple number + return n.toString() + } else if (m < SISym.length) { + // with SI suffix + return f.toFixed(2) + SISym[m] + } else { + // scientific notation + m *= 3 + while (f > 10) { + f /= 10 + m++ + } + return f.toFixed(2) + 'e' + m + } + +} + +///////////////////////////////////////////////////////////////////////// +// end of file \ No newline at end of file diff --git a/src/model/services.js b/src/model/services.js new file mode 100644 index 0000000..56f3271 --- /dev/null +++ b/src/model/services.js @@ -0,0 +1,90 @@ +///////////////////////////////////////////////////////////////////////// +// level functions + +export class Services { + constructor() { + + this.time = { + unlocked: false, + level: 0, + + } + this.auto = { + unlocked: false, + level: 0 + } + + } + + // save data + save() { + let save_data = { + time: this.time, + auto: this.auto + } + return save_data + } + + restore(save_data) { + Object.assign(this, save_data) + } + + tick(state, interval) { + if (state.levels[2].count > 0) { this.auto.unlocked = true } + if (state.levels[3].count > 0) { this.time.unlocked = true } + } + + // time costs + tCost() { + switch (this.time.level) { + case 0: + return 1000000n + case 1: + return 1000000000n + default: + return 0n + } + } + + tUnits(state) { + return state.levels[(this.time.level*2)+3].units + } + + tValue(state) { + return state.levels[(this.time.level*2)+3].count + } + + tUpgrade(state) { + state.levels[(this.time.level*2)+3].count -= this.tCost() + this.time.level++ + } + + // auto costs + aCost() { + switch (this.auto.level) { + case 0: + return 1000000n + case 1: + return 1000000000n + default: + return 0n + } + } + + aUnits(state) { + return state.levels[(this.auto.level*2)+2].units + } + + aValue(state) { + return state.levels[(this.auto.level*2)+2].count + } + + aUpgrade(state) { + state.levels[(this.auto.level*2)+2].count -= this.aCost() + this.auto.level++ + } + +} + +///////////////////////////////////////////////////////////////////////// +// end of file \ No newline at end of file diff --git a/src/model/state.js b/src/model/state.js new file mode 100644 index 0000000..5d1575c --- /dev/null +++ b/src/model/state.js @@ -0,0 +1,133 @@ +///////////////////////////////////////////////////////////////////////// + +import { defineStore } from "pinia" +import { computed, reactive } from "vue" +import { LevelDefs } from './leveldefs.js' +import { Bandwidth } from './bandwidth.js' +import { Autobuyer } from "./autobuyer.js" +import { Services } from "./services.js" + +///////////////////////////////////////////////////////////////////////// + +export const useState = defineStore('state', () => { + + // timer tick + function tick(state, i) { + let interval = BigInt(i) + ui.elapsed += i + + // update bandwidth + bandwidth.tick(state, interval) + + // update levels + levels.forEach((l) => { + l.tick(state, interval) + }) + + ui.save = ((ui.elapsed % 30) == 0) + if (ui.save) { save() } + + autobuyer.tick(state, i) + services.tick(state, i) + } + + // save and restore + function reset() { + localStorage.clear() + location.reload() + } + + function save() { + + let save_data = { + version: version, + elapsed: ui.elapsed, + levels: Array.from(levels, (l) => l.save()), + bandwidth: bandwidth.save(), + services: services.save(), + autobuyer: autobuyer.save() + } + + // replacer func to handle big ints + const replacer = (key, value) => + typeof value === 'bigint' ? '__big__' + value.toString() : value + let encoded = JSON.stringify(save_data, replacer) + + localStorage.setItem('clicker42', encoded) + } + + function restore() { + let encoded = localStorage.getItem('clicker42') + if (!encoded) { return } + + // reviver func to handle big ints + const reviver = (key, value) => + ((typeof value === 'string') && (value.startsWith('__big__'))) ? BigInt(value.substring(7)) : value; + let save_data = JSON.parse(encoded, reviver) + + // don't load older versions + if (version > save_data.version) { return } + + ui.elapsed = save_data.elapsed + + // restore levels + save_data.levels.forEach((l) => { + let index = l.index + levels[index].restore(l) + }) + + // and bandwidth + bandwidth.restore(save_data.bandwidth) + services.restore(save_data.services) + autobuyer.restore(save_data.autobuyer) + } + + function noticeClear() { + ui.notice = ' ' + } + + function noticeTemplate(style, text) { + ui.notice = '' + text + '' + } + + function noticeSuccess(text) { noticeTemplate('bg-success', text) } + function noticeDanger(text) { noticeTemplate('bg-danger', text) } + + // game data + const version = 0.1 + const ui = reactive({ + selectedLevel: 0, + elapsed: 0, + notice: ' ', + save: false + }) + const autobuyer = reactive(new Autobuyer()) + + // level data + const levels = reactive(LevelDefs) + levels.forEach((l, ix) => { + l.index = ix + l.multiplier = BigInt(ix) + }) + + const bandwidth = reactive(new Bandwidth()) + const services = reactive(new Services()) + + // computed functions + const count = computed(() => levels.length) + + // return the things that will form part of the store + return { + // data + version, ui, levels, bandwidth, services, autobuyer, + // computed + count, + // functions + tick, reset, save, restore, + noticeClear, noticeSuccess, noticeDanger + } + +}) + +///////////////////////////////////////////////////////////////////////// +// end of file \ No newline at end of file diff --git a/src/style.css b/src/style.css deleted file mode 100644 index 84a0050..0000000 --- a/src/style.css +++ /dev/null @@ -1,89 +0,0 @@ -:root { - font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; - font-weight: 400; - - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} -a:hover { - color: #535bf2; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} -a:hover { - color: #535bf2; -} - -body { - margin: 0; - display: flex; - place-items: center; - min-width: 320px; - min-height: 100vh; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; -} -button:hover { - border-color: #646cff; -} -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; -} - -.card { - padding: 2em; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - a:hover { - color: #747bff; - } - button { - background-color: #f9f9f9; - } -} diff --git a/yarn.lock b/yarn.lock index b3619b0..58f822a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -164,6 +164,11 @@ "@vue/compiler-dom" "3.2.47" "@vue/shared" "3.2.47" +"@vue/devtools-api@^6.5.0": + version "6.5.0" + resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.5.0.tgz#98b99425edee70b4c992692628fa1ea2c1e57d07" + integrity sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q== + "@vue/reactivity-transform@3.2.47": version "3.2.47" resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.2.47.tgz#e45df4d06370f8abf29081a16afd25cffba6d84e" @@ -212,6 +217,16 @@ resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.47.tgz#e597ef75086c6e896ff5478a6bfc0a7aa4bbd14c" integrity sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ== +bootstrap-icons@^1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/bootstrap-icons/-/bootstrap-icons-1.10.3.tgz#c587b078ca6743bef4653fe90434b4aebfba53b2" + integrity sha512-7Qvj0j0idEm/DdX9Q0CpxAnJYqBCFCiUI6qzSPYfERMcokVuV9Mdm/AJiVZI8+Gawe4h/l6zFcOzvV7oXCZArw== + +bootstrap@^5.2.3: + version "5.2.3" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.2.3.tgz#54739f4414de121b9785c5da3c87b37ff008322b" + integrity sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ== + csstype@^2.6.8: version "2.6.21" resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.21.tgz#2efb85b7cc55c80017c66a5ad7cbd931fda3a90e" @@ -296,6 +311,14 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +pinia@^2.0.33: + version "2.0.33" + resolved "https://registry.yarnpkg.com/pinia/-/pinia-2.0.33.tgz#b70065be697874d5824e9792f59bd5d87ddb5e7d" + integrity sha512-HOj1yVV2itw6rNIrR2f7+MirGNxhORjrULL8GWgRwXsGSvEqIQ+SE0MYt6cwtpegzCda3i+rVTZM+AM7CG+kRg== + dependencies: + "@vue/devtools-api" "^6.5.0" + vue-demi "*" + postcss@^8.1.10, postcss@^8.4.21: version "8.4.21" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4" @@ -353,6 +376,11 @@ vite@^4.2.0: optionalDependencies: fsevents "~2.3.2" +vue-demi@*: + version "0.13.11" + resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.13.11.tgz#7d90369bdae8974d87b1973564ad390182410d99" + integrity sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A== + vue@^3.2.47: version "3.2.47" resolved "https://registry.yarnpkg.com/vue/-/vue-3.2.47.tgz#3eb736cbc606fc87038dbba6a154707c8a34cff0"