Add basic plan generator

This commit is contained in:
tree 2022-05-14 18:15:08 +02:00
rodič 846fb9d7f5
revize c99d0082a1
6 změnil soubory, kde provedl 367 přidání a 2 odebrání

Zobrazit soubor

@ -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

Zobrazit soubor

@ -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

Zobrazit soubor

@ -22,6 +22,7 @@ specDef:
- type: speakers
- type: tracks
- type: events
- type: stages
- type: faqs
- type: partners
- type: projects

68
spec/22/stages.yaml Normal file
Zobrazit soubor

@ -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'

223
utils/plan.js Normal file
Zobrazit soubor

@ -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();

Zobrazit soubor

@ -64,4 +64,12 @@ properties:
- beginner
- advanced
- expert
fixed:
type: object
additionalProperties: false
properties:
time:
type: string
stage:
type: string