Update
This commit is contained in:
rodič
c99d0082a1
revize
c1950e833b
2
Makefile
2
Makefile
|
@ -68,4 +68,4 @@ changelog:
|
|||
deno run --unstable --allow-read --allow-write --allow-run utils/changelog.js
|
||||
|
||||
plan:
|
||||
deno run --unstable --allow-read utils/plan.js
|
||||
deno run --unstable --allow-read --allow-write utils/plan.js
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
- id: cbdc-panel
|
||||
type: panel
|
||||
name: CBDC – cesta do monetárního otroctví
|
||||
track: regulace
|
||||
speakers:
|
||||
- lukas-kovanda
|
||||
- dominik-stroukal
|
||||
|
@ -153,6 +154,8 @@
|
|||
- volný trh
|
||||
- finanční svoboda
|
||||
- anarchokapitalismus
|
||||
fixed:
|
||||
stage: rajska-zahrada
|
||||
|
||||
- id: historie-cypherpunku
|
||||
type: talk
|
||||
|
@ -290,6 +293,8 @@
|
|||
speakers: [ artur-sychov ]
|
||||
duration: 25
|
||||
difficulty: beginner
|
||||
fixed:
|
||||
stage: rajska-zahrada
|
||||
tags:
|
||||
- Metaverse
|
||||
- NFT
|
||||
|
@ -411,16 +416,6 @@
|
|||
description: |
|
||||
Představení základů pracovních poměrů a finančních iniciativ v kryptoměnách. Podíváme se, kde nejlépe sledovat nové nabídky a jak ve zkratce fungují dnešní DAOs.
|
||||
|
||||
- id: zijeme-bez-fiatu
|
||||
type: talk
|
||||
name: Žijeme bez fiatu
|
||||
track: zaklady
|
||||
speakers: [ vladimir-pinker ]
|
||||
duration: 55
|
||||
difficulty: beginner
|
||||
tags:
|
||||
- finanční nezávislost
|
||||
|
||||
- id: guildy-odf-dao-organizacni-revoluce
|
||||
type: talk
|
||||
name: Guildy, ODF a DAO jako organizační revoluce
|
||||
|
@ -710,16 +705,6 @@
|
|||
- finanční nezávislost
|
||||
|
||||
|
||||
- id: je-krypto-letadlo
|
||||
type: talk
|
||||
name: Je krypto letadlo?
|
||||
track: zaklady
|
||||
speakers: [ vladimir-pinker ]
|
||||
duration: 25
|
||||
difficulty: beginner
|
||||
tags:
|
||||
- letectví
|
||||
|
||||
- id: investovani-20
|
||||
type: talk
|
||||
name: Investování 2.0
|
||||
|
@ -841,6 +826,7 @@
|
|||
Představení lokálních česko-slovenských kryptoměnových komunit.
|
||||
tags:
|
||||
- společnost
|
||||
duration: 85
|
||||
|
||||
- id: lokalni-projekty-intro
|
||||
type: lightning-series
|
||||
|
@ -849,6 +835,31 @@
|
|||
speakers: []
|
||||
description: |
|
||||
Představení lokálních kryptoměnových projektů.
|
||||
tags:
|
||||
- Bitcoin
|
||||
duration: 55
|
||||
|
||||
- id: lokalni-btc-intro
|
||||
type: lightning-series
|
||||
name: Lokální Bitcoin projekty
|
||||
track: btc
|
||||
speakers: []
|
||||
description: |
|
||||
Představení lokálních bitcoinově zaměřených projektů.
|
||||
duration: 55
|
||||
tags:
|
||||
- Bitcoin
|
||||
|
||||
- id: lokalni-dao-intro
|
||||
type: lightning-series
|
||||
name: Lokální DAO projekty
|
||||
track: dao
|
||||
speakers: []
|
||||
description: |
|
||||
Představení lokálních DAO projektů.
|
||||
duration: 25
|
||||
tags:
|
||||
- DAO
|
||||
|
||||
- id: lokalni-defi-intro
|
||||
type: lightning-series
|
||||
|
@ -859,6 +870,7 @@
|
|||
- DeFi
|
||||
description: |
|
||||
Představení lokálních DeFi projektů.
|
||||
duration: 55
|
||||
|
||||
|
||||
- id: lokalni-nft-intro
|
||||
|
@ -870,6 +882,7 @@
|
|||
- NFT
|
||||
description: |
|
||||
Představení lokálních NFT/Metaverse projektů.
|
||||
duration: 55
|
||||
|
||||
|
||||
# Workshops (workshopy)
|
||||
|
@ -1223,7 +1236,7 @@
|
|||
track: btc
|
||||
speakers: [ honza-dvorak ]
|
||||
duration: 10
|
||||
parent: lokalni-projekty-intro
|
||||
parent: lokalni-btc-intro
|
||||
tags:
|
||||
- Bitcoin
|
||||
- platby
|
||||
|
@ -1234,7 +1247,7 @@
|
|||
track: btc
|
||||
speakers: [ mario-havel ]
|
||||
duration: 10
|
||||
parent: lokalni-projekty-intro
|
||||
parent: lokalni-btc-intro
|
||||
tags:
|
||||
- Bitcoin
|
||||
- Lightning Network
|
||||
|
@ -1247,7 +1260,7 @@
|
|||
track: btc
|
||||
speakers: [ kristian-csepcsar ]
|
||||
duration: 10
|
||||
parent: lokalni-projekty-intro
|
||||
parent: lokalni-btc-intro
|
||||
tags:
|
||||
- Bitcoin
|
||||
- mining
|
||||
|
@ -1259,6 +1272,7 @@
|
|||
track: btc
|
||||
speakers: [ kryptomates ]
|
||||
duration: 10
|
||||
parent: lokalni-btc-intro
|
||||
tags:
|
||||
- Bitcoin
|
||||
- Lightning Network
|
||||
|
@ -1368,15 +1382,15 @@
|
|||
description: |
|
||||
Umíte-li ovládat internetové bankovnictví, tak umíte ovládat i decentralizované finance. Přes jedno webové rozhraní si lidé mohou půjčit peníze, spořit nebo investovat. Představíme si komunitní projekt, který zpřístupňuje decentralizované finance běžným lidem.
|
||||
|
||||
- id: liqwid
|
||||
type: lightning
|
||||
name: Liqwid Finance
|
||||
track: alty
|
||||
speakers: [ mark-stopka ]
|
||||
duration: 10
|
||||
parent: lokalni-defi-intro
|
||||
tags:
|
||||
- DeFi
|
||||
# - id: liqwid
|
||||
# type: lightning
|
||||
# name: Liqwid Finance
|
||||
# track: alty
|
||||
# speakers: [ mark-stopka ]
|
||||
# duration: 10
|
||||
# parent: lokalni-defi-intro
|
||||
# tags:
|
||||
# - DeFi
|
||||
|
||||
- id: stosujcz
|
||||
type: lightning
|
||||
|
@ -1466,17 +1480,17 @@
|
|||
- NFT
|
||||
- metaverse
|
||||
|
||||
- id: bankless-cz
|
||||
type: lightning
|
||||
name: Bankless.cz
|
||||
track: zaklady
|
||||
speakers: []
|
||||
duration: 10
|
||||
parent: lokalni-komunity-intro
|
||||
tags:
|
||||
- komunity
|
||||
- Bitcoin
|
||||
- Ethereum
|
||||
# - id: bankless-cz
|
||||
# type: lightning
|
||||
# name: Bankless.cz
|
||||
# track: zaklady
|
||||
# speakers: []
|
||||
# duration: 10
|
||||
# parent: lokalni-komunity-intro
|
||||
# tags:
|
||||
# - komunity
|
||||
# - Bitcoin
|
||||
# - Ethereum
|
||||
|
||||
- id: polkadotters
|
||||
type: lightning
|
||||
|
@ -1520,7 +1534,7 @@
|
|||
track: eth
|
||||
speakers: []
|
||||
duration: 10
|
||||
parent: lokalni-projekty-intro
|
||||
parent: lokalni-dao-intro
|
||||
tags:
|
||||
- Ethereum
|
||||
- DAO
|
||||
|
@ -1533,7 +1547,7 @@
|
|||
track: eth
|
||||
speakers: [ rene-darmos ]
|
||||
duration: 10
|
||||
parent: lokalni-projekty-intro
|
||||
parent: lokalni-dao-intro
|
||||
tags:
|
||||
- DAO
|
||||
|
||||
|
@ -1600,6 +1614,8 @@
|
|||
tags:
|
||||
- komunity
|
||||
- ženy
|
||||
fixed:
|
||||
stage: campfire-outdoor
|
||||
|
||||
- id: dydx-intro
|
||||
type: campfire
|
||||
|
@ -1612,6 +1628,26 @@
|
|||
- Ethereum
|
||||
- StarkWare
|
||||
|
||||
- id: je-krypto-letadlo
|
||||
type: campfire
|
||||
name: Je krypto letadlo?
|
||||
track: zaklady
|
||||
speakers: [ vladimir-pinker ]
|
||||
duration: 30
|
||||
difficulty: beginner
|
||||
tags:
|
||||
- letectví
|
||||
|
||||
- id: zijeme-bez-fiatu
|
||||
type: campfire
|
||||
name: Žijeme bez fiatu
|
||||
track: zaklady
|
||||
speakers: [ vladimir-pinker ]
|
||||
duration: 55
|
||||
difficulty: beginner
|
||||
tags:
|
||||
- finanční nezávislost
|
||||
|
||||
|
||||
# Ostatní
|
||||
# ==========================
|
||||
|
@ -1620,6 +1656,7 @@
|
|||
type: other
|
||||
name: UTXO.Party - Elektronická stage
|
||||
speakers: [ dmitry ]
|
||||
duration: 360
|
||||
fixed:
|
||||
time: '1/20:00-23:59'
|
||||
stage: pitevna
|
||||
|
@ -1628,6 +1665,7 @@
|
|||
type: other
|
||||
name: Ukončení konference
|
||||
speakers: [ tereza-starostova, tree ]
|
||||
duration: 30
|
||||
fixed:
|
||||
time: '2/18:30-19:00'
|
||||
stage: rajska-zahrada
|
||||
|
@ -1636,6 +1674,7 @@
|
|||
type: other
|
||||
name: Slavnostní zahájení konference 🎉
|
||||
speakers: [ tereza-starostova ]
|
||||
duration: 30
|
||||
fixed:
|
||||
time: '1/09:00-09:30'
|
||||
stage: rajska-zahrada
|
||||
|
|
|
@ -80,8 +80,8 @@
|
|||
tracks: [ zaklady, btc, dao, spolecnost ]
|
||||
country: sk
|
||||
available:
|
||||
- from: '2022-06-04T09:00:00'
|
||||
to: '2022-06-05T12:59:59'
|
||||
- from: '2022-06-04T09:00:00+02:00'
|
||||
to: '2022-06-05T12:59:59+02:00'
|
||||
|
||||
- id: vladimir-pinker
|
||||
name: Vladimír Pinker
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
- '2/14:00-19:00'
|
||||
|
||||
- id: sloupcovy-sal
|
||||
types: [ talk ]
|
||||
types: [ talk, lightning-series ]
|
||||
times:
|
||||
- '1/09:30-13:00'
|
||||
- '1/14:00-19:00'
|
||||
|
|
215
utils/plan.js
215
utils/plan.js
|
@ -1,5 +1,6 @@
|
|||
import { format, parse } from "https://deno.land/std@0.139.0/datetime/mod.ts";
|
||||
import { UTXOEngine } from "./engine.js";
|
||||
import { MultiProgressBar } from "https://deno.land/x/progress@v1.2.4/mod.ts";
|
||||
|
||||
const utxo = new UTXOEngine({ silent: true });
|
||||
await utxo.init();
|
||||
|
@ -7,8 +8,28 @@ const entry = utxo.entries["22"];
|
|||
const specs = entry.specs;
|
||||
const index = entry.index;
|
||||
|
||||
function shuffle(array) {
|
||||
let currentIndex = array.length, randomIndex;
|
||||
|
||||
// While there remain elements to shuffle.
|
||||
while (currentIndex != 0) {
|
||||
// Pick a remaining element.
|
||||
randomIndex = Math.floor(Math.random() * currentIndex);
|
||||
currentIndex--;
|
||||
|
||||
// And swap it with the current element.
|
||||
[array[currentIndex], array[randomIndex]] = [
|
||||
array[randomIndex],
|
||||
array[currentIndex],
|
||||
];
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
class UTXOPlanner {
|
||||
constructor() {
|
||||
this.eventsAll = specs.events;
|
||||
this.eventsOriginal = specs.events.filter((ev) =>
|
||||
ev.type !== "lightning" && ev.duration
|
||||
);
|
||||
|
@ -17,6 +38,7 @@ class UTXOPlanner {
|
|||
this.startTime = new Date();
|
||||
this.schedule = [];
|
||||
this.unscheduled = [];
|
||||
this.priorityLevel = 10;
|
||||
this.tries = {};
|
||||
|
||||
// normalize stages
|
||||
|
@ -27,7 +49,19 @@ class UTXOPlanner {
|
|||
const haveAfter = this.events.find((e) =>
|
||||
e.after === ev.id || e.rightAfter === ev.id
|
||||
);
|
||||
ev.priority = haveAfter ? 10 : 0;
|
||||
ev.priority = haveAfter ? 10 : (ev.after || ev.rightAfter ? 5 : 0);
|
||||
|
||||
if (ev.type === "lightning-series") {
|
||||
let sarr = [];
|
||||
for (
|
||||
const sp of this.eventsAll.filter((e) => e.parent === ev.id).map(
|
||||
(e) => e.speakers
|
||||
)
|
||||
) {
|
||||
sarr = sarr.concat(sp);
|
||||
}
|
||||
ev.speakers = sarr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,14 +77,15 @@ class UTXOPlanner {
|
|||
|
||||
addEvent(ev, data) {
|
||||
this.schedule.push({
|
||||
date: format(data.period.start, "yyyy-MM-dd"),
|
||||
stage: data.stage,
|
||||
period: data.period,
|
||||
event: ev.id,
|
||||
});
|
||||
this.events.splice(this.events.indexOf(ev), 1);
|
||||
console.log(
|
||||
/*console.log(
|
||||
`Event ${ev.id} scheduled: ${data.stage} ${JSON.stringify(data.period)}`,
|
||||
);
|
||||
);*/
|
||||
}
|
||||
|
||||
addFixedEvent(ev) {
|
||||
|
@ -88,7 +123,7 @@ class UTXOPlanner {
|
|||
const skipSegments = Math.floor(Math.random() * stage.timesFull.length) - 1;
|
||||
let segmentCount = 0;
|
||||
|
||||
for (const segment of stage.timesFull) {
|
||||
for (const segment of shuffle(stage.timesFull)) {
|
||||
segmentCount++;
|
||||
if (segmentCount >= skipSegments) {
|
||||
let ctime = segment.start;
|
||||
|
@ -97,9 +132,9 @@ class UTXOPlanner {
|
|||
if (evPeriod.end.getTime() <= segment.end.getTime()) {
|
||||
const conflicts = this.findConflicts(stage, evPeriod);
|
||||
if (conflicts === 0) {
|
||||
return evPeriod;
|
||||
//this.addEvent(ev, { stage: stage.id, period: evPeriod })
|
||||
//return null
|
||||
if (this.eventSlotValidator(ev, evPeriod, stage)) {
|
||||
return evPeriod;
|
||||
}
|
||||
}
|
||||
}
|
||||
ctime = new Date(ctime.getTime() + slotDuration);
|
||||
|
@ -113,7 +148,20 @@ class UTXOPlanner {
|
|||
x.end.getTime() > y.start.getTime());
|
||||
}
|
||||
|
||||
eventSlotValidator(ev, slot) {
|
||||
eventSlotValidator(ev, slot, stage) {
|
||||
// check "rightAfter"
|
||||
if (ev.rightAfter) {
|
||||
const target = this.schedule.find((si) => si.event === ev.rightAfter);
|
||||
if (!target) {
|
||||
return false;
|
||||
}
|
||||
if (target.stage !== stage.id) {
|
||||
return false;
|
||||
}
|
||||
if (target.period.end.getTime() !== slot.start.getTime()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// check speakers
|
||||
for (const si of this.schedule) {
|
||||
const sev = this.eventsOriginal.find((e) => e.id === si.event);
|
||||
|
@ -127,11 +175,36 @@ class UTXOPlanner {
|
|||
}
|
||||
}
|
||||
}
|
||||
// check speakers availability
|
||||
for (const spId of ev.speakers) {
|
||||
const sp = specs.speakers.find((s) => s.id === spId);
|
||||
if (!sp) {
|
||||
continue;
|
||||
}
|
||||
if (sp.available) {
|
||||
let okey = false;
|
||||
for (const spa of sp.available) {
|
||||
if (
|
||||
this.isPeriodOverlap({
|
||||
start: new Date(spa.from),
|
||||
end: new Date(spa.to),
|
||||
}, slot)
|
||||
) {
|
||||
okey = true;
|
||||
}
|
||||
}
|
||||
if (!okey) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
iterate() {
|
||||
const priorityEvents = this.events.filter((e) => e.priority > 0);
|
||||
|
||||
const events = priorityEvents.length > 0 ? priorityEvents : this.events;
|
||||
|
||||
const rand = Math.floor(Math.random() * events.length);
|
||||
|
@ -149,20 +222,29 @@ class UTXOPlanner {
|
|||
this.tries[ev.id] = 0;
|
||||
}
|
||||
this.tries[ev.id]++;
|
||||
if (this.tries[ev.id] > 5000) {
|
||||
if (this.tries[ev.id] > 10) {
|
||||
this.events.splice(this.events.indexOf(ev), 1);
|
||||
this.unscheduled.push(ev.id);
|
||||
return null;
|
||||
}
|
||||
|
||||
const randStage = Math.floor(Math.random() * availStages.length);
|
||||
const stage = this.stages.find((s) => s.id === availStages[randStage]);
|
||||
let stage = null;
|
||||
if (ev.fixed && ev.fixed.stage) {
|
||||
if (!availStages.includes(ev.fixed.stage)) {
|
||||
return null;
|
||||
}
|
||||
stage = this.stages.find((s) => s.id === ev.fixed.stage);
|
||||
} else {
|
||||
const randStage = Math.floor(Math.random() * availStages.length);
|
||||
stage = this.stages.find((s) => s.id === availStages[randStage]);
|
||||
}
|
||||
|
||||
const slot = this.findSlotInStage(ev, stage);
|
||||
if (slot) {
|
||||
const valid = this.eventSlotValidator(ev, slot);
|
||||
if (valid) {
|
||||
this.addEvent(ev, { stage: stage.id, period: slot });
|
||||
}
|
||||
//const valid = this.eventSlotValidator(ev, slot, stage);
|
||||
//if (valid) {
|
||||
this.addEvent(ev, { stage: stage.id, period: slot });
|
||||
//}
|
||||
}
|
||||
|
||||
const diff = (new Date()).getTime() - this.startTime.getTime();
|
||||
|
@ -174,7 +256,9 @@ class UTXOPlanner {
|
|||
|
||||
plan() {
|
||||
// nejprve umistime fixed
|
||||
for (const ev of this.events.filter((e) => e.fixed && e.fixed.time)) {
|
||||
for (
|
||||
const ev of this.eventsOriginal.filter((e) => e.fixed && e.fixed.time)
|
||||
) {
|
||||
this.addFixedEvent(ev);
|
||||
}
|
||||
|
||||
|
@ -182,7 +266,59 @@ class UTXOPlanner {
|
|||
this.iterate();
|
||||
}
|
||||
|
||||
this.renderResults();
|
||||
// calculate metrics
|
||||
for (const si of this.schedule) {
|
||||
const ev = this.eventsOriginal.find((e) => e.id === si.event);
|
||||
|
||||
// calculate themes crossing
|
||||
const crossings = [];
|
||||
for (const ssi of this.schedule) {
|
||||
if (ssi.event === si.event) {
|
||||
continue;
|
||||
}
|
||||
if (this.isPeriodOverlap(si.period, ssi.period)) {
|
||||
const eev = this.eventsOriginal.find((e) => e.id === ssi.event);
|
||||
const tagsCrossing = ev.tags.reduce((prev, cur) =>
|
||||
prev + (eev.tags.includes(cur)
|
||||
? 0
|
||||
: 1), 0) / ev.tags.length;
|
||||
crossings.push([
|
||||
ev.track === eev.track
|
||||
? 0
|
||||
: 1,
|
||||
tagsCrossing,
|
||||
ssi,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
si.metrics = {
|
||||
themeCrossing: (crossings.reduce((prev, cur) =>
|
||||
prev + cur[0], 0) / crossings.length),
|
||||
tagsCrossing: (crossings.reduce((prev, cur) =>
|
||||
prev + cur[1], 0) / crossings.length),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
calcScheduleMetric(metric) {
|
||||
return this.schedule.reduce(
|
||||
(prev, cur) =>
|
||||
prev + (cur.metrics && cur.metrics[metric] ? cur.metrics[metric] : 1),
|
||||
0,
|
||||
) / this.schedule.length;
|
||||
}
|
||||
|
||||
metrics() {
|
||||
const cols = ["themeCrossing", "tagsCrossing"];
|
||||
const obj = {};
|
||||
let total = 0;
|
||||
for (const col of cols) {
|
||||
obj[col] = this.calcScheduleMetric(col);
|
||||
total += obj[col];
|
||||
}
|
||||
obj.score = total / cols.length;
|
||||
return obj;
|
||||
}
|
||||
|
||||
formatTime() {
|
||||
|
@ -219,5 +355,46 @@ class UTXOPlanner {
|
|||
}
|
||||
}
|
||||
|
||||
const planner = new UTXOPlanner();
|
||||
planner.plan();
|
||||
async function main() {
|
||||
const limit = 100000;
|
||||
let i = 0;
|
||||
console.log("Planning started ..");
|
||||
|
||||
const plans = [];
|
||||
|
||||
while (i < limit) {
|
||||
const planner = new UTXOPlanner();
|
||||
planner.plan();
|
||||
//console.log(JSON.stringify(planner.unscheduled))
|
||||
|
||||
if (planner.unscheduled.length === 0) {
|
||||
//planner.renderResults()
|
||||
const metrics = planner.metrics();
|
||||
console.log(
|
||||
`solution #${
|
||||
plans.length + 1
|
||||
} : score ${metrics.score} {themeCrossing: ${metrics.themeCrossing}, tagsCrossing: ${metrics.tagsCrossing}}`,
|
||||
);
|
||||
//console.log(`----\nPlan found after ${i} tries`)
|
||||
//break
|
||||
plans.push({ schedule: planner.schedule, metrics });
|
||||
}
|
||||
|
||||
if (plans.length >= 10) {
|
||||
const outputFn = "./dist/22/schedule.json";
|
||||
console.log(`Writing result: ${outputFn}`);
|
||||
const filtered = plans.sort((x, y) =>
|
||||
x.metrics.score > y.metrics.score ? -1 : 1
|
||||
).slice(0, 20);
|
||||
Deno.writeTextFile(outputFn, JSON.stringify(filtered, null, 2));
|
||||
break;
|
||||
}
|
||||
|
||||
if (i % 100 === 0) {
|
||||
console.log(`${i}/${limit} - solutions: ${plans.length}`);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
|
|
Načítá se…
Odkázat v novém úkolu