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? path string session &base.Session @[skip; str: skip] } @[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 // we ignore prio's above 49 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.actions[id - 1] or { panic('bug in actions sorted') } res << a } } return res } @[params] pub struct HeroScriptArgs { pub mut: show_done bool } // 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) out += '\n\n' 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 // filter 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) 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 // } // } // @[deprecated: "Use plbook.get(filter: 'actor.name') or plbook.get(id: id) instead."] // pub fn (mut plbook PlayBook) action_get(args ActionGetArgs) !&Action { // if args.id != 0 { // return plbook.actions[args.id-1] or { panic("bug in action get") } // } // return plbook.get(filter: '${args.actor}.${args.name}')! // } 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 plbook 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') } }