Add basic plan generator
This commit is contained in:
rodič
846fb9d7f5
revize
c99d0082a1
3
Makefile
3
Makefile
|
@ -66,3 +66,6 @@ media-kit:
|
|||
|
||||
changelog:
|
||||
deno run --unstable --allow-read --allow-write --allow-run utils/changelog.js
|
||||
|
||||
plan:
|
||||
deno run --unstable --allow-read utils/plan.js
|
||||
|
|
|
@ -23,10 +23,14 @@
|
|||
|
||||
- id: nft-metaverse-panel
|
||||
type: panel
|
||||
name: NFT a Metaverse
|
||||
name: NFT a Metaverse [TBD]
|
||||
speakers:
|
||||
- vojta-zizka
|
||||
- petr-mara
|
||||
- resistance
|
||||
- david-bankless
|
||||
properties:
|
||||
moderators: [ vojta-zizka ]
|
||||
duration: 85
|
||||
difficulty: beginner
|
||||
track: nft
|
||||
|
@ -34,6 +38,30 @@
|
|||
- NFT
|
||||
- metaverse
|
||||
|
||||
- id: nft-usecases-panel
|
||||
type: panel
|
||||
name: NFT Use Cases [TBD]
|
||||
speakers:
|
||||
- lenka-hudakova
|
||||
- petr-mara
|
||||
duration: 85
|
||||
difficulty: advanced
|
||||
track: nft
|
||||
tags:
|
||||
- NFT
|
||||
- metaverse
|
||||
|
||||
- id: nft-curation-art-heritage
|
||||
type: panel
|
||||
name: NFT curation/art/heritage [TBD]
|
||||
speakers: []
|
||||
duration: 85
|
||||
difficulty: beginner
|
||||
track: nft
|
||||
tags:
|
||||
- NFT
|
||||
- umění
|
||||
|
||||
- id: czk-stablecoin-panel
|
||||
type: panel
|
||||
name: Decentralizováná krypto-koruna (CZK stablecoin)
|
||||
|
@ -296,13 +324,15 @@
|
|||
|
||||
- id: social-tokeny
|
||||
type: talk
|
||||
name: Sociální tokeny (Social Tokens)
|
||||
name: Social Token Salad
|
||||
track: eth
|
||||
speakers: [ michaela-malatin ]
|
||||
duration: 55
|
||||
difficulty: advanced
|
||||
tags:
|
||||
- sociální tokeny
|
||||
description: |
|
||||
Social Token je kategorie krypto aktiv, která není takřka probádána a přitom má velký potenciál. Někteří zaměňují NFT za Social Token. Nejsou stejné (ERC-721 vs. ERC-20), naopak se doplňují. Je to jako míchat jablka s hruškami. Nejsou stejné, ale je z nich skvělý salát. Pojďme si spolu projít recept na skvělou strategii propagace jednotlivce, projektů nebo si jen osvojit možnost vlastního tokenu.
|
||||
|
||||
- id: od-mozku-k-blockchainu-decentralizovana-veda-desci
|
||||
type: talk
|
||||
|
@ -391,6 +421,20 @@
|
|||
tags:
|
||||
- finanční nezávislost
|
||||
|
||||
- id: guildy-odf-dao-organizacni-revoluce
|
||||
type: talk
|
||||
name: Guildy, ODF a DAO jako organizační revoluce
|
||||
track: dao
|
||||
speakers: [ michaela-malatin ]
|
||||
duration: 55
|
||||
difficulty: advanced
|
||||
tags:
|
||||
- DAO
|
||||
- organizace
|
||||
- společnost
|
||||
description: |
|
||||
Existují principy, které vytvořili decentralizaci a opensource, jak jej známe dnes a není to white paper Bitcoinu. Herní guildy, Open Decision Framework a Decentralized Autonomous Organization mají jedno společné. Meritokracie. Kašlete na volební právo v DAO, Discordové skupiny nebo vymazlené white papery. Pokud nemáte systém rovnosti, vášně pro danou věc a misi v každém jednotlivci, nemáte šanci v oceánu novodobých organizačních systémech. Budu s vámi sdílet mé zkušenosti s Development teamy, kde se mísí komunita a strategie.
|
||||
|
||||
- id: hypoteky-pro-cryptonatives
|
||||
type: talk
|
||||
name: Hypotéky pro Cryptonatives
|
||||
|
@ -1576,4 +1620,22 @@
|
|||
type: other
|
||||
name: UTXO.Party - Elektronická stage
|
||||
speakers: [ dmitry ]
|
||||
fixed:
|
||||
time: '1/20:00-23:59'
|
||||
stage: pitevna
|
||||
|
||||
- id: closing-ceremony
|
||||
type: other
|
||||
name: Ukončení konference
|
||||
speakers: [ tereza-starostova, tree ]
|
||||
fixed:
|
||||
time: '2/18:30-19:00'
|
||||
stage: rajska-zahrada
|
||||
|
||||
- id: opening-ceremony
|
||||
type: other
|
||||
name: Slavnostní zahájení konference 🎉
|
||||
speakers: [ tereza-starostova ]
|
||||
fixed:
|
||||
time: '1/09:00-09:30'
|
||||
stage: rajska-zahrada
|
||||
|
|
|
@ -22,6 +22,7 @@ specDef:
|
|||
- type: speakers
|
||||
- type: tracks
|
||||
- type: events
|
||||
- type: stages
|
||||
- type: faqs
|
||||
- type: partners
|
||||
- type: projects
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
- id: rajska-zahrada
|
||||
types: [ talk, panel, lightning-series ]
|
||||
times:
|
||||
- '1/09:00-13:00'
|
||||
- '1/14:00-18:30'
|
||||
- '2/10:00-13:00'
|
||||
- '2/14:00-19:00'
|
||||
|
||||
- id: sloupcovy-sal
|
||||
types: [ talk ]
|
||||
times:
|
||||
- '1/09:30-13:00'
|
||||
- '1/14:00-19:00'
|
||||
- '2/10:00-13:00'
|
||||
- '2/14:00-18:30'
|
||||
|
||||
- id: lustrovy-sal
|
||||
types: [ talk, panel, lightning-series ]
|
||||
times:
|
||||
- '1/09:30-13:00'
|
||||
- '1/14:00-19:00'
|
||||
- '2/10:00-13:00'
|
||||
- '2/14:00-18:30'
|
||||
|
||||
- id: exit-room
|
||||
types: [ talk ]
|
||||
times:
|
||||
- '1/09:30-13:00'
|
||||
- '1/14:00-19:00'
|
||||
- '2/10:00-13:00'
|
||||
- '2/14:00-18:30'
|
||||
|
||||
- id: knihovna
|
||||
types: [ workshop ]
|
||||
times:
|
||||
- '1/09:30-13:00'
|
||||
- '1/14:00-19:00'
|
||||
- '2/10:00-13:00'
|
||||
- '2/14:00-18:30'
|
||||
|
||||
- id: white-workshop-room
|
||||
types: [ workshop ]
|
||||
times:
|
||||
- '1/09:30-13:00'
|
||||
- '1/14:00-19:00'
|
||||
- '2/10:00-13:00'
|
||||
- '2/14:00-18:30'
|
||||
|
||||
- id: campfire-outdoor
|
||||
types: [ campfire ]
|
||||
times:
|
||||
- '1/09:30-13:00'
|
||||
- '1/14:00-19:00'
|
||||
- '2/10:00-13:00'
|
||||
- '2/14:00-18:30'
|
||||
|
||||
- id: campfire-indoor
|
||||
types: [ campfire ]
|
||||
times:
|
||||
- '1/09:30-13:00'
|
||||
- '1/14:00-19:00'
|
||||
- '2/10:00-13:00'
|
||||
- '2/14:00-18:30'
|
||||
|
||||
- id: pitevna
|
||||
types: [ other ]
|
||||
times:
|
||||
- '1/16:00-23:59'
|
|
@ -0,0 +1,223 @@
|
|||
import { format, parse } from "https://deno.land/std@0.139.0/datetime/mod.ts";
|
||||
import { UTXOEngine } from "./engine.js";
|
||||
|
||||
const utxo = new UTXOEngine({ silent: true });
|
||||
await utxo.init();
|
||||
const entry = utxo.entries["22"];
|
||||
const specs = entry.specs;
|
||||
const index = entry.index;
|
||||
|
||||
class UTXOPlanner {
|
||||
constructor() {
|
||||
this.eventsOriginal = specs.events.filter((ev) =>
|
||||
ev.type !== "lightning" && ev.duration
|
||||
);
|
||||
this.events = JSON.parse(JSON.stringify(this.eventsOriginal));
|
||||
this.stages = specs.stages;
|
||||
this.startTime = new Date();
|
||||
this.schedule = [];
|
||||
this.unscheduled = [];
|
||||
this.tries = {};
|
||||
|
||||
// normalize stages
|
||||
for (const stage of this.stages) {
|
||||
stage.timesFull = stage.times.map((st) => this.parsePeriod(st));
|
||||
}
|
||||
for (const ev of this.events) {
|
||||
const haveAfter = this.events.find((e) =>
|
||||
e.after === ev.id || e.rightAfter === ev.id
|
||||
);
|
||||
ev.priority = haveAfter ? 10 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
parsePeriod(str) {
|
||||
const [dayNumber, period] = str.split("/");
|
||||
const [start, end] = period.split("-");
|
||||
const date = index.dates[Number(dayNumber) - 1];
|
||||
return {
|
||||
start: parse(`${date} ${start}`, "yyyy-MM-dd HH:mm"),
|
||||
end: parse(`${date} ${end}`, "yyyy-MM-dd HH:mm"),
|
||||
};
|
||||
}
|
||||
|
||||
addEvent(ev, data) {
|
||||
this.schedule.push({
|
||||
stage: data.stage,
|
||||
period: data.period,
|
||||
event: ev.id,
|
||||
});
|
||||
this.events.splice(this.events.indexOf(ev), 1);
|
||||
console.log(
|
||||
`Event ${ev.id} scheduled: ${data.stage} ${JSON.stringify(data.period)}`,
|
||||
);
|
||||
}
|
||||
|
||||
addFixedEvent(ev) {
|
||||
this.addEvent(ev, {
|
||||
stage: ev.fixed.stage,
|
||||
period: this.parsePeriod(ev.fixed.time),
|
||||
});
|
||||
}
|
||||
|
||||
findConflicts(stage, period) {
|
||||
const evs = this.schedule.filter((s) => s.stage === stage.id);
|
||||
for (const si of evs) {
|
||||
if (
|
||||
si.period.start.getTime() < period.end.getTime() &&
|
||||
si.period.end.getTime() > period.start.getTime()
|
||||
) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
eventPeriod(ev, start) {
|
||||
return {
|
||||
start,
|
||||
end: new Date(
|
||||
start.getTime() + (Math.ceil(ev.duration / 30) * 30) * 60 * 1000,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
findSlotInStage(ev, stage) {
|
||||
const slotDuration = 15 * 60 * 1000;
|
||||
const stageEvents = this.schedule.filter((s) => s.stage === stage.id);
|
||||
const skipSegments = Math.floor(Math.random() * stage.timesFull.length) - 1;
|
||||
let segmentCount = 0;
|
||||
|
||||
for (const segment of stage.timesFull) {
|
||||
segmentCount++;
|
||||
if (segmentCount >= skipSegments) {
|
||||
let ctime = segment.start;
|
||||
while (ctime.getTime() < segment.end.getTime()) {
|
||||
const evPeriod = this.eventPeriod(ev, ctime);
|
||||
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
|
||||
}
|
||||
}
|
||||
ctime = new Date(ctime.getTime() + slotDuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isPeriodOverlap(x, y) {
|
||||
return (x.start.getTime() < y.end.getTime() &&
|
||||
x.end.getTime() > y.start.getTime());
|
||||
}
|
||||
|
||||
eventSlotValidator(ev, slot) {
|
||||
// check speakers
|
||||
for (const si of this.schedule) {
|
||||
const sev = this.eventsOriginal.find((e) => e.id === si.event);
|
||||
const speakers = ev.speakers.reduce(
|
||||
(prev, current) => sev.speakers.includes(current) ? prev + 1 : prev,
|
||||
0,
|
||||
);
|
||||
if (speakers > 0) {
|
||||
if (this.isPeriodOverlap(si.period, slot)) {
|
||||
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);
|
||||
const ev = events[rand];
|
||||
|
||||
const availStages = this.stages.filter((st) => st.types.includes(ev.type))
|
||||
.map((s) => s.id);
|
||||
if (availStages.length === 0) {
|
||||
this.events.splice(this.events.indexOf(ev), 1);
|
||||
this.unscheduled.push(ev.id);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!this.tries[ev.id]) {
|
||||
this.tries[ev.id] = 0;
|
||||
}
|
||||
this.tries[ev.id]++;
|
||||
if (this.tries[ev.id] > 5000) {
|
||||
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]);
|
||||
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 diff = (new Date()).getTime() - this.startTime.getTime();
|
||||
if ((new Date()).getTime() - this.startTime.getTime() > (1000 * 3)) {
|
||||
console.log(this.events.map((e) => e.id));
|
||||
}
|
||||
//Deno.exit()
|
||||
}
|
||||
|
||||
plan() {
|
||||
// nejprve umistime fixed
|
||||
for (const ev of this.events.filter((e) => e.fixed && e.fixed.time)) {
|
||||
this.addFixedEvent(ev);
|
||||
}
|
||||
|
||||
while (this.events.length > 0) {
|
||||
this.iterate();
|
||||
}
|
||||
|
||||
this.renderResults();
|
||||
}
|
||||
|
||||
formatTime() {
|
||||
}
|
||||
|
||||
renderResults() {
|
||||
console.log("----------------");
|
||||
for (const date of index.dates) {
|
||||
const dateItems = this.schedule.filter((s) => {
|
||||
return s.period.start.getTime() <
|
||||
parse(`${date} 23:59`, "yyyy-MM-dd HH:mm").getTime() &&
|
||||
s.period.start.getTime() >
|
||||
parse(`${date} 00:00`, "yyyy-MM-dd HH:mm").getTime();
|
||||
});
|
||||
console.log(`[${date}]`);
|
||||
for (const stage of this.stages) {
|
||||
console.log(` [${stage.id}]`);
|
||||
const items = dateItems.filter((s) => s.stage === stage.id).sort((
|
||||
x,
|
||||
y,
|
||||
) => x.period.start > y.period.start ? 1 : -1);
|
||||
for (const item of items) {
|
||||
console.log(
|
||||
` ${format(item.period.start, "HH:mm")}-${
|
||||
format(item.period.end, "HH:mm")
|
||||
} ~ ${item.event}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(
|
||||
`Events: ${this.eventsOriginal.length}, assigned: ${this.schedule.length}, unscheduled: ${this.unscheduled}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const planner = new UTXOPlanner();
|
||||
planner.plan();
|
|
@ -64,4 +64,12 @@ properties:
|
|||
- beginner
|
||||
- advanced
|
||||
- expert
|
||||
fixed:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
time:
|
||||
type: string
|
||||
stage:
|
||||
type: string
|
||||
|
||||
|
|
Načítá se…
Odkázat v novém úkolu