Files
herolib/lib/core/playbook/playbook.v
2024-12-25 08:40:56 +01:00

203 lines
5.1 KiB
V

module playbook
import freeflowuniverse.herolib.core.base
import freeflowuniverse.herolib.core.texttools
import freeflowuniverse.herolib.data.paramsparser
import crypto.blake2b
@[heap]
pub struct PlayBook {
pub mut:
actions []&Action
priorities map[int][]int // first key is the priority, the list of int's is position in list self.actions
othertext string // in case there is text outside of the actions
result string // if any result
nractions int
done []int // which actions did we already find/run?
session &base.Session
}
@[params]
pub struct ActionNewArgs {
pub mut:
cid string
name string
actor string
priority int = 10 // 0 is highest, do 10 as default
// run bool = true // certain actions can be defined but meant to be executed directly
actiontype ActionType
}
// add action to the book
fn (mut plbook PlayBook) action_new(args ActionNewArgs) &Action {
plbook.nractions += 1
mut a := Action{
id: plbook.nractions
cid: args.cid
name: args.name
actor: args.actor
priority: args.priority
// run: args.run
actiontype: args.actiontype
params: paramsparser.Params{}
result: paramsparser.Params{}
}
plbook.actions << &a
return &a
}
pub fn (mut plbook PlayBook) str() string {
return plbook.heroscript() or { 'Cannot visualize playbook properly.\n${plbook.actions}' }
}
@[params]
pub struct SortArgs {
pub mut:
prio_only bool // if true only show the actions which were prioritized before
}
// only return the actions which are not done yet
// if filtered is set, it means we only get the ones which were prioritized before
pub fn (mut plbook PlayBook) actions_sorted(args SortArgs) ![]&Action {
mut res := []&Action{}
mut nrs := plbook.priorities.keys()
nrs.sort()
if nrs.len == 0 {
// means sorting did not happen before
return plbook.actions
}
for nr in nrs {
if args.prio_only && nr > 49 {
continue
}
action_ids := plbook.priorities[nr] or { panic('bug') }
for id in action_ids {
mut a := plbook.action_get(id: id)!
res << a
}
}
return res
}
@[params]
pub struct HeroScriptArgs {
pub mut:
show_done bool = true
}
// serialize to heroscript
pub fn (mut plbook PlayBook) heroscript(args HeroScriptArgs) !string {
mut out := ''
for action in plbook.actions_sorted()! {
if args.show_done == false && action.done {
continue
}
out += '${action.heroscript()}\n'
}
if plbook.othertext.len > 0 {
out += '${plbook.othertext}'
}
out = texttools.remove_empty_js_blocks(out)
return out
}
// return list of names .
// the names are normalized (no special chars, lowercase, ... )
pub fn (mut plbook PlayBook) names() ![]string {
mut names := []string{}
for action in plbook.actions_sorted()! {
names << action.name
}
return names
}
@[params]
pub struct ActionGetArgs {
pub mut:
id int
actor string
name string
actiontype ActionType = .sal
}
// Find all actions based on ActionGetArgs
// - If id == 0, then matches all ids; when id is specified, can only return 1.
// - If actor == "", then matches all actors.
// - If name == "", then matches all actions from the defined actor (if defined).
// - If actiontype == .unknown, then matches all action types; when specified, filters by the action type, default .sal
pub fn (mut plbook PlayBook) actions_find(args ActionGetArgs) ![]&Action {
mut res := []&Action{}
for a in plbook.actions {
// If id is specified, return only the action with that id
if args.id != 0 {
if a.id == args.id {
return [a]
}
continue
}
// Filter by actor if specified
if args.actor.len > 0 && a.actor != args.actor {
continue
}
// Filter by name if specified
if args.name.len > 0 && a.name != args.name {
continue
}
// Filter by actiontype if specified
if args.actiontype != .unknown && a.actiontype != args.actiontype {
continue
}
// If the action passes all filters, add it to the result
res << a
}
return res
}
pub fn (mut plbook PlayBook) action_exists(args ActionGetArgs) bool {
// Use actions_find to get the filtered actions
actions := plbook.actions_find(args) or { return false }
if actions.len == 1 {
return true
} else if actions.len == 0 {
return false
} else {
return false
}
}
pub fn (mut plbook PlayBook) action_get(args ActionGetArgs) !&Action {
// Use actions_find to get the filtered actions
actions := plbook.actions_find(args)!
if actions.len == 1 {
return actions[0]
} else if actions.len == 0 {
return error("couldn't find action with args: ${args}")
} else {
return error('multiple actions found with args: ${args}, expected only one')
}
}
pub fn (plbook PlayBook) hashkey() string {
mut out := []string{}
for action in plbook.actions {
out << action.hashkey()
}
txt := out.join_lines()
bs := blake2b.sum160(txt.bytes())
return bs.hex()
}
// check if playbook is empty,if not will give error, means there are actions left to be exected
pub fn (mut plbook PlayBook) empty_check() ! {
mut actions := []&Action{}
for a in plbook.actions {
if a.done == false {
actions << a
}
}
if actions.len > 0 {
msg := plbook.heroscript(show_done: false)!
return error('There are actions left to execute, see below:\n\n${msg}\n\n')
}
}