Merge branch 'development_bizmodel' into development_generator_docusaurus
* development_bizmodel: (93 commits) s Revert "test: add cmdline parser tests" test: add cmdline parser tests markdown code ... revert ... ..deployments ... bump version to 1.0.21 ... bump version to 1.0.20 ... fix tests and example bump version to 1.0.19 bump version to 1.0.18 bump version to 1.0.17 ... ... bump version to 1.0.16 ... # Conflicts: # lib/web/docusaurus/config.v
This commit is contained in:
14
.gitignore
vendored
14
.gitignore
vendored
@@ -1,4 +1,13 @@
|
||||
|
||||
# Additional ignore files and directories
|
||||
Thumbs.db
|
||||
# Logs
|
||||
logs/
|
||||
*.log
|
||||
*.out
|
||||
# Compiled Python files
|
||||
*.pyc
|
||||
*.pyo
|
||||
__pycache__/
|
||||
*dSYM/
|
||||
.vmodules/
|
||||
.vscode
|
||||
@@ -28,4 +37,5 @@ output/
|
||||
.stellar
|
||||
data.ms/
|
||||
test_basic
|
||||
cli/hero
|
||||
cli/hero
|
||||
.aider*
|
||||
|
||||
@@ -51,7 +51,7 @@ fn do() ! {
|
||||
mut cmd := Command{
|
||||
name: 'hero'
|
||||
description: 'Your HERO toolset.'
|
||||
version: '1.0.13'
|
||||
version: '1.0.21'
|
||||
}
|
||||
|
||||
// herocmds.cmd_run_add_flags(mut cmd)
|
||||
@@ -102,6 +102,7 @@ fn do() ! {
|
||||
// herocmds.cmd_juggler(mut cmd)
|
||||
herocmds.cmd_generator(mut cmd)
|
||||
herocmds.cmd_docusaurus(mut cmd)
|
||||
herocmds.cmd_starlight(mut cmd)
|
||||
// herocmds.cmd_docsorter(mut cmd)
|
||||
// cmd.add_command(publishing.cmd_publisher(pre_func))
|
||||
cmd.setup()
|
||||
|
||||
11
examples/biztools/_archive/investor_tool.vsh
Executable file
11
examples/biztools/_archive/investor_tool.vsh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.biz.investortool
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import os
|
||||
|
||||
mut plbook := playbook.new(
|
||||
path: '${os.home_dir()}/code/git.ourworld.tf/ourworld_holding/investorstool/output'
|
||||
)!
|
||||
mut it := investortool.play(mut plbook)!
|
||||
it.check()!
|
||||
48
examples/biztools/_archive/tf9_biz.vsh
Executable file
48
examples/biztools/_archive/tf9_biz.vsh
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env -S v -cg -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
// #!/usr/bin/env -S v -cg -enable-globals run
|
||||
import freeflowuniverse.herolib.data.doctree
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.biz.bizmodel
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import freeflowuniverse.herolib.core.playcmds
|
||||
import freeflowuniverse.herolib.web.mdbook
|
||||
import freeflowuniverse.herolib.biz.spreadsheet
|
||||
import os
|
||||
|
||||
const name = 'tf9_budget'
|
||||
|
||||
const wikipath = '${os.home_dir()}/code/git.ourworld.tf/ourworld_holding/info_ourworld/collections/${name}'
|
||||
const summarypath = '${wikipath}/summary.md'
|
||||
|
||||
// mut sh := spreadsheet.sheet_new(name: 'test2') or { panic(err) }
|
||||
// println(sh)
|
||||
// sh.row_new(descr: 'this is a description', name: 'something', growth: '0:100aed,55:1000eur')!
|
||||
// println(sh)
|
||||
// println(sh.wiki()!)
|
||||
|
||||
// exit(0)
|
||||
|
||||
// execute the actions so we have the info populated
|
||||
// mut plb:=playbook.new(path: wikipath)!
|
||||
// playcmds.run(mut plb,false)!
|
||||
|
||||
buildpath := '${os.home_dir()}/hero/var/mdbuild/bizmodel'
|
||||
|
||||
// just run the doctree & mdbook and it should
|
||||
// load the doctree, these are all collections
|
||||
mut tree := doctree.new(name: name)!
|
||||
tree.scan(path: wikipath)!
|
||||
tree.export(dest: buildpath, reset: true)!
|
||||
|
||||
// mut bm:=bizmodel.get("test")!
|
||||
// println(bm)
|
||||
|
||||
mut mdbooks := mdbook.get()!
|
||||
mdbooks.generate(
|
||||
name: 'bizmodel'
|
||||
summary_path: summarypath
|
||||
doctree_path: buildpath
|
||||
title: 'bizmodel ${name}'
|
||||
)!
|
||||
mdbook.book_open('bizmodel')!
|
||||
12
examples/biztools/_archive/todo.md
Normal file
12
examples/biztools/_archive/todo.md
Normal file
@@ -0,0 +1,12 @@
|
||||
need to find where the manual is
|
||||
|
||||
- [manual](bizmodel_example/configuration.md)
|
||||
- [widgets](bizmodel_example/widgets.md)
|
||||
- [graph_bar_row](bizmodel_example/graph_bar_row.md)
|
||||
- [sheet_tables](bizmodel_example/sheet_tables.md)
|
||||
- [widget_args](bizmodel_example/widget_args.md)
|
||||
- [params](bizmodel_example/configuration.md)
|
||||
- [revenue params](bizmodel_example/revenue_params.md)
|
||||
- [funding params](bizmodel_example/funding_params.md)
|
||||
- [hr params](bizmodel_example/hr_params.md)
|
||||
- [costs params](bizmodel_example/costs_params.md)
|
||||
25
examples/biztools/bizmodel.vsh
Executable file
25
examples/biztools/bizmodel.vsh
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env -S v -n -w -cg -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
//#!/usr/bin/env -S v -cg -enable-globals run
|
||||
import freeflowuniverse.herolib.biz.bizmodel
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import freeflowuniverse.herolib.core.playcmds
|
||||
import os
|
||||
|
||||
const playbook_path = os.dir(@FILE) + '/playbook'
|
||||
const build_path = os.join_path(os.dir(@FILE), '/docusaurus')
|
||||
|
||||
buildpath := '${os.home_dir()}/hero/var/mdbuild/bizmodel'
|
||||
|
||||
mut model := bizmodel.getset("example")!
|
||||
model.workdir = build_path
|
||||
model.play(mut playbook.new(path: playbook_path)!)!
|
||||
|
||||
println(model.sheet)
|
||||
println(model.sheet.export()!)
|
||||
|
||||
model.sheet.export(path:"~/Downloads/test.csv")!
|
||||
model.sheet.export(path:"~/code/github/freeflowuniverse/starlight_template/src/content/test.csv")!
|
||||
|
||||
|
||||
|
||||
4
examples/biztools/bizmodel_docusaurus/.gitignore
vendored
Normal file
4
examples/biztools/bizmodel_docusaurus/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
bizmodel
|
||||
dest
|
||||
wiki
|
||||
build
|
||||
1
examples/biztools/bizmodel_docusaurus/archive/img/.done
Normal file
1
examples/biztools/bizmodel_docusaurus/archive/img/.done
Normal file
@@ -0,0 +1 @@
|
||||
ms1bmodel.png
|
||||
BIN
examples/biztools/bizmodel_docusaurus/archive/img/ms1bmodel.png
Normal file
BIN
examples/biztools/bizmodel_docusaurus/archive/img/ms1bmodel.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
13
examples/biztools/bizmodel_docusaurus/archive/revenue.md
Normal file
13
examples/biztools/bizmodel_docusaurus/archive/revenue.md
Normal file
@@ -0,0 +1,13 @@
|
||||
## Revenue
|
||||
|
||||
Overview of achieved revenue.
|
||||
|
||||
Unit is in Million USD.
|
||||
|
||||
!!bizmodel.sheet_wiki title:'REVENUE' includefilter:rev sheetname:'bizmodel_test'
|
||||
|
||||
!!bizmodel.graph_bar_row rowname:revenue_total unit:million sheetname:'bizmodel_test'
|
||||
|
||||
!!bizmodel.graph_line_row rowname:revenue_total unit:million sheetname:'bizmodel_test'
|
||||
|
||||
!!bizmodel.graph_pie_row rowname:revenue_total unit:million size:'80%' sheetname:'bizmodel_test'
|
||||
13
examples/biztools/bizmodel_docusaurus/archive/summary.md
Normal file
13
examples/biztools/bizmodel_docusaurus/archive/summary.md
Normal file
@@ -0,0 +1,13 @@
|
||||
- [bizmodel](bizmodel_example/bizmodel.md)
|
||||
- [Revenue](bizmodel_example/revenue.md)
|
||||
- [Result](bizmodel_example/overview.md)
|
||||
- [parameters](bizmodel_example/params.md)
|
||||
- [revenue_params](bizmodel_example/params/revenue_params.md)
|
||||
- [funding_params](bizmodel_example/params/funding_params.md)
|
||||
- [hr_params](bizmodel_example/params/hr_params.md)
|
||||
- [costs_params](bizmodel_example/params/costs_params.md)
|
||||
- [rows overview](bizmodel_example/rows_overview.md)
|
||||
- [employees](bizmodel_example/employees.md)
|
||||
- [debug](bizmodel_example/debug.md)
|
||||
- [worksheet](bizmodel_example/worksheet.md)
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# Overview of the rows in the biz model sheet
|
||||
|
||||
|
||||
!!bizmodel.sheet_wiki sheetname:'bizmodel_test'
|
||||
37
examples/biztools/bizmodel_docusaurus/bizmodel_docusaurus.vsh
Executable file
37
examples/biztools/bizmodel_docusaurus/bizmodel_docusaurus.vsh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env -S v -n -w -cg -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
//#!/usr/bin/env -S v -cg -enable-globals run
|
||||
import freeflowuniverse.herolib.biz.bizmodel
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
import freeflowuniverse.herolib.core.playcmds
|
||||
import os
|
||||
|
||||
//TODO: need to fix wrong location
|
||||
const playbook_path = os.dir(@FILE) + '/playbook'
|
||||
const build_path = os.join_path(os.dir(@FILE), '/docusaurus')
|
||||
|
||||
buildpath := '${os.home_dir()}/hero/var/mdbuild/bizmodel'
|
||||
|
||||
mut model := bizmodel.getset("example")!
|
||||
model.workdir = build_path
|
||||
model.play(mut playbook.new(path: playbook_path)!)!
|
||||
|
||||
println(model.sheet)
|
||||
println(model.sheet.export()!)
|
||||
|
||||
// model.sheet.export(path:"~/Downloads/test.csv")!
|
||||
// model.sheet.export(path:"~/code/github/freeflowuniverse/starlight_template/src/content/test.csv")!
|
||||
|
||||
|
||||
|
||||
|
||||
report := model.new_report(
|
||||
name: 'example_report'
|
||||
title: 'Example Business Model'
|
||||
)!
|
||||
|
||||
report.export(
|
||||
path: build_path
|
||||
overwrite: true
|
||||
format: .docusaurus
|
||||
)!
|
||||
@@ -0,0 +1 @@
|
||||
output dir of example
|
||||
22
examples/biztools/bizmodel_docusaurus/docusaurus/build.sh
Executable file
22
examples/biztools/bizmodel_docusaurus/docusaurus/build.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "${script_dir}"
|
||||
|
||||
echo "Docs directory: $script_dir"
|
||||
|
||||
cd "${HOME}/hero/var/docusaurus"
|
||||
|
||||
export PATH=/tmp/docusaurus_build/node_modules/.bin:${HOME}/.bun/bin/:$PATH
|
||||
|
||||
rm -rf /Users/despiegk/hero/var/docusaurus/build/
|
||||
|
||||
. ${HOME}/.zprofile
|
||||
|
||||
bun docusaurus build
|
||||
|
||||
mkdir -p /Users/despiegk/code/github/freeflowuniverse/herolib/examples/biztools/bizmodel/example/docusaurus
|
||||
echo SYNC TO /Users/despiegk/code/github/freeflowuniverse/herolib/examples/biztools/bizmodel/example/docusaurus
|
||||
rsync -rv --delete /Users/despiegk/hero/var/docusaurus/build/ /Users/despiegk/code/github/freeflowuniverse/herolib/examples/biztools/bizmodel/example/docusaurus/
|
||||
@@ -0,0 +1 @@
|
||||
{"style":"dark","links":[]}
|
||||
@@ -0,0 +1 @@
|
||||
{"name":"","title":"Docusaurus","tagline":"","favicon":"img/favicon.png","url":"http://localhost","url_home":"docs/introduction","baseUrl":"/","image":"img/tf_graph.png","metadata":{"description":"Docusaurus","image":"Docusaurus","title":"Docusaurus"},"buildDest":[],"buildDestDev":[]}
|
||||
@@ -0,0 +1 @@
|
||||
{"title":"Business Model","items":[{"href":"https://threefold.info/kristof/","label":"ThreeFold Technology","position":"right"},{"href":"https://threefold.io","label":"Operational Plan","position":"left"}]}
|
||||
16
examples/biztools/bizmodel_docusaurus/docusaurus/develop.sh
Executable file
16
examples/biztools/bizmodel_docusaurus/docusaurus/develop.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "${script_dir}"
|
||||
|
||||
echo "Docs directory: $script_dir"
|
||||
|
||||
cd "${HOME}/hero/var/docusaurus"
|
||||
|
||||
export PATH=/tmp/docusaurus_build/node_modules/.bin:${HOME}/.bun/bin/:$PATH
|
||||
|
||||
. ${HOME}/.zprofile
|
||||
|
||||
bun run start -p 3100
|
||||
10
examples/biztools/bizmodel_docusaurus/load.md
Normal file
10
examples/biztools/bizmodel_docusaurus/load.md
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
## Loader instructions
|
||||
|
||||
this will make sure we load the appropriate biz model
|
||||
|
||||
|
||||
```js
|
||||
!!bizmodel.load name:'default' url:'https://github.com/freeflowuniverse/herolib/tree/development/bizmodel/example/data'
|
||||
```
|
||||
|
||||
1
examples/biztools/playbook/.collection
Normal file
1
examples/biztools/playbook/.collection
Normal file
@@ -0,0 +1 @@
|
||||
name:bizmodel_example
|
||||
10
examples/biztools/playbook/bizmodel.md
Normal file
10
examples/biztools/playbook/bizmodel.md
Normal file
@@ -0,0 +1,10 @@
|
||||

|
||||
|
||||
# bizmodel
|
||||
|
||||
OurWorld has developed a tool to generate and keep business models up to date.
|
||||
|
||||
Our aim is to make it easy for ourworld to track changes in planning over the multiple projects and even be able to aggregated them. Because the input for such a plan is text (as you can see in this ebook) its easy to see how the modelling and parameters change over time.
|
||||
|
||||
This is a very flexible tool which will be extended for budgetting, cashflow management, shareholder tables, ...
|
||||
|
||||
31
examples/biztools/playbook/cost_centers.md
Normal file
31
examples/biztools/playbook/cost_centers.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# HR Params
|
||||
|
||||
## Engineering
|
||||
|
||||
Costs can be grouped in cost centers which can then be used to futher process e.g. transcactions between companies.
|
||||
|
||||
```js
|
||||
|
||||
!!bizmodel.costcenter_define bizname:'test'
|
||||
name:'tfdmcc'
|
||||
descr:'TFDMCC executes on near source agreement for TFTech'
|
||||
min_month:'10000USD'
|
||||
max_month:'100000USD'
|
||||
end_date:'1/1/2026' //when does agreement stop
|
||||
|
||||
!!bizmodel.costcenter_define bizname:'test'
|
||||
name:'cs_tftech'
|
||||
descr:'Nearsource agreement for TFTech towards Codescalers'
|
||||
min_month:'10000USD'
|
||||
max_month:'100000USD'
|
||||
end_date:'1/1/2026'
|
||||
|
||||
!!bizmodel.costcenter_define bizname:'test'
|
||||
name:'cs_tfcloud'
|
||||
descr:'Nearsource agreement for TFCloud towards Codescalers'
|
||||
min_month:'10000USD'
|
||||
max_month:'100000USD'
|
||||
end_date:'1/1/2026'
|
||||
|
||||
|
||||
```
|
||||
39
examples/biztools/playbook/costs_params.md
Normal file
39
examples/biztools/playbook/costs_params.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Generic Overhead Costs
|
||||
|
||||
possible parameters
|
||||
|
||||
- name
|
||||
- descr: description of the cost
|
||||
- cost: is 'month:amount,month:amount, ...', no extrapolation
|
||||
- cost_growth: is 'month:amount,month:amount, ..., or just a nr', will extrapolate
|
||||
- type: travel, admin, legal, varia, office
|
||||
- cost_percent_revenue e.g. 4%, will make sure the cost will be at least 4% of revenue
|
||||
- indexation, e.g. 2%
|
||||
|
||||
Other financial flows can be mentioned here as well.
|
||||
|
||||
|
||||
```js
|
||||
!!bizmodel.cost_define bizname:'test'
|
||||
name:'rental'
|
||||
descr:'Office Rental in BE.'
|
||||
cost:'5000'
|
||||
indexation:'2%'
|
||||
type:'office'
|
||||
|
||||
!!bizmodel.cost_define bizname:'test'
|
||||
name:'oneoff'
|
||||
descr:'Event in Z.'
|
||||
cost_one:'3:50000'
|
||||
type:'event'
|
||||
|
||||
!!bizmodel.cost_define bizname:'test'
|
||||
name:'cloud'
|
||||
descr:'Datacenter and Cloud Costs'
|
||||
cost:'2000eur'
|
||||
cost_percent_revenue:'2%'
|
||||
type:'cloud'
|
||||
|
||||
|
||||
```
|
||||
|
||||
4
examples/biztools/playbook/debug.md
Normal file
4
examples/biztools/playbook/debug.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# Debug
|
||||
|
||||
Some tools and info to help debug the bizmodel simulator.
|
||||
|
||||
20
examples/biztools/playbook/department_params.md
Normal file
20
examples/biztools/playbook/department_params.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Department Params
|
||||
|
||||
```js
|
||||
|
||||
!!bizmodel.department_define bizname:'test'
|
||||
name:'ops'
|
||||
title:'Operations'
|
||||
order:5
|
||||
|
||||
!!bizmodel.department_define bizname:'test'
|
||||
name:'coordination'
|
||||
title:'Coordination'
|
||||
order:1
|
||||
|
||||
!!bizmodel.department_define bizname:'test'
|
||||
name:'engineering'
|
||||
title:'Engineering'
|
||||
order:4
|
||||
|
||||
```
|
||||
29
examples/biztools/playbook/funding_params.md
Normal file
29
examples/biztools/playbook/funding_params.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Funding Params
|
||||
|
||||
possible parameters
|
||||
|
||||
- name, e.g. for a specific person
|
||||
- descr: description of the funding
|
||||
- investment is month:amount,month:amount, ...
|
||||
- type: loan or capital
|
||||
|
||||
Other financial flows can be mentioned here as well.
|
||||
|
||||
|
||||
```js
|
||||
!!bizmodel.funding_define bizname:'test'
|
||||
name:'our_investor'
|
||||
descr:'A fantastic super investor.'
|
||||
investment:'3:1000000EUR'
|
||||
type:'capital'
|
||||
|
||||
!!bizmodel.funding_define bizname:'test'
|
||||
name:'a_founder'
|
||||
descr:'Together Are Strong'
|
||||
investment:'2000000'
|
||||
type:'loan'
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
73
examples/biztools/playbook/hr_params.md
Normal file
73
examples/biztools/playbook/hr_params.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# HR Params
|
||||
|
||||
## Engineering
|
||||
|
||||
possible parameters
|
||||
|
||||
- descr, description of the function (e.g. master architect)
|
||||
- cost, any currency eg. 1000usd
|
||||
- in case cost changes over time e.g. 1:10000USD,20:20000USD,60:30000USD
|
||||
- indexation, e.g. 2%
|
||||
- department
|
||||
- name, e.g. for a specific person
|
||||
- nrpeople: how many people per month, growth over time notation e.g. 1:10,60:20 means 10 in month 1 growing to 20 month 60
|
||||
- cost_percent_revenue e.g. 4%, will make sure the cost will be at least 4% of revenue
|
||||
|
||||
```js
|
||||
|
||||
!!bizmodel.employee_define bizname:'test'
|
||||
sid:2
|
||||
descr:'Senior Engineer'
|
||||
cost:'1:12000,12:14000' //cost is always per person
|
||||
department:'engineering'
|
||||
nrpeople:'0:5,20:5'
|
||||
|
||||
!!bizmodel.employee_define bizname:'test'
|
||||
name:'despiegk'
|
||||
title: 'CTO and crazy inventor.'
|
||||
sid:3
|
||||
descr:'CTO'
|
||||
cost:'12000EUR' //the salary is the cost independent of the fulltime status
|
||||
indexation:'10%'
|
||||
department:'coordination'
|
||||
page:'cto.md'
|
||||
fulltime: "50%" //100% means yes
|
||||
|
||||
!!bizmodel.employee_define bizname:'test'
|
||||
descr:'Senior Architect'
|
||||
cost:'10000USD' indexation:'5%'
|
||||
department:'engineering'
|
||||
nrpeople:'0:5,20:10'
|
||||
|
||||
!!bizmodel.employee_define bizname:'test'
|
||||
descr:'Junior Engineer'
|
||||
cost:'4000USD' indexation:'5%'
|
||||
department:'engineering'
|
||||
nrpeople:'0:5,20:10'
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Operations
|
||||
|
||||
```js
|
||||
|
||||
!!bizmodel.employee_define bizname:'test'
|
||||
descr:'Ops Manager'
|
||||
cost:'1:8000,12:14000'
|
||||
department:'ops'
|
||||
!!bizmodel.employee_define bizname:'test'
|
||||
descr:'Support Junior'
|
||||
cost:'2000EUR' indexation:'5%'
|
||||
department:'ops'
|
||||
nrpeople:'7:5,18:10'
|
||||
cost_percent_revenue:'1%'
|
||||
!!bizmodel.employee_define bizname:'test'
|
||||
descr:'Support Senior'
|
||||
cost:'5000EUR' indexation:'5%'
|
||||
department:'ops'
|
||||
nrpeople:'3:5,20:10'
|
||||
cost_percent_revenue:'1%'
|
||||
costcenter:'tfdmcc:25,cs_tfcloud:75'
|
||||
generate_page:'../employees/support_senior.md'
|
||||
```
|
||||
14
examples/biztools/playbook/params.md
Normal file
14
examples/biztools/playbook/params.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Bizmodel Params
|
||||
|
||||
In this section we can find all the parameters for the bizmodel.
|
||||
|
||||
## how to use and read
|
||||
|
||||
The params are defined in the different instruction files e.g. revenue_params.md
|
||||
|
||||
Often you will see something like `revenue_growth:'10:1000,20:1100'` this can be read as month 10 it 1000, month 20 its 1100.
|
||||
|
||||
The software will extrapolate.
|
||||
|
||||
|
||||
|
||||
85
examples/biztools/playbook/revenue_params.md
Normal file
85
examples/biztools/playbook/revenue_params.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# HR Params
|
||||
|
||||
## Revenue Items (non recurring)
|
||||
|
||||
This company is a cloud company ...
|
||||
|
||||
- name, e.g. for a specific project
|
||||
- descr, description of the revenue line item
|
||||
- revenue_items: does one of revenue, is not exterpolated
|
||||
- revenue_growth: is a revenue stream which is being extrapolated
|
||||
- revenue_setup, revenue for 1 item '1000usd'
|
||||
- revenue_setup_delay
|
||||
- revenue_monthly, revenue per month for 1 item
|
||||
- revenue_monthly_delay, how many months before monthly revenue starts
|
||||
- maintenance_month_perc, how much percent of revenue_setup will come back over months
|
||||
- cogs_setup, cost of good for 1 item at setup
|
||||
- cogs_setup_delay, how many months before setup cogs starts, after sales
|
||||
- cogs_setup_perc: what is percentage of the cogs (can change over time) for setup e.g. 0:50%
|
||||
|
||||
- cogs_monthly, cost of goods for the monthly per 1 item
|
||||
- cogs_monthly_delay, how many months before monthly cogs starts, after sales
|
||||
- cogs_monthly_perc: what is percentage of the cogs (can change over time) for monthly e.g. 0:5%,12:10%
|
||||
|
||||
- nr_sold: how many do we sell per month (is in growth format e.g. 10:100,20:200, default is 1)
|
||||
- nr_months_recurring: how many months is recurring, if 0 then no recurring
|
||||
|
||||
```js
|
||||
!!bizmodel.revenue_define bizname:'test'
|
||||
descr:'OEM Deals'
|
||||
revenue_items:'10:1000000EUR,15:3333,20:1200000'
|
||||
cogs_setup_perc: '1:5%,20:10%'
|
||||
|
||||
!!bizmodel.revenue_define bizname:'test'
|
||||
descr:'License Deals'
|
||||
revenue_growth:'10:1000,20:1100'
|
||||
cogs_perc: '10%'
|
||||
rev_delay_month: 1
|
||||
|
||||
!!bizmodel.revenue_define bizname:'test'
|
||||
descr:'3NODE License Sales 1 Time'
|
||||
//means revenue is 100 month 1, 200 month 60
|
||||
revenue_item:'1:100,60:200'
|
||||
revenue_nr:'10:1000,24:2000,60:40000'
|
||||
cogs_perc: '10%'
|
||||
rev_delay_month: 1
|
||||
|
||||
```
|
||||
|
||||
## Revenue Items Recurring
|
||||
|
||||
possible parameters
|
||||
|
||||
- name, e.g. for a specific project
|
||||
- descr, description of the revenue line item
|
||||
- revenue_setup, revenue for 1 item '1000usd'
|
||||
- revenue_monthly, revenue per month for 1 item
|
||||
- revenue_setup_delay, how many months before revenue comes in after sales
|
||||
- revenue_monthly_delay, how many months before monthly revenue starts
|
||||
- cogs_setup, cost of good for 1 item at setup
|
||||
- cogs_setup_perc: what is percentage of the cogs (can change over time) for setup e.g. 0:50%
|
||||
- cogs_monthly, cost of goods for the monthly per 1 item
|
||||
- cogs_monthly_perc: what is percentage of the cogs (can change over time) for monthly e.g. 0:5%,12:10%
|
||||
- nr_sold: how many do we sell per month (is in growth format e.g. 10:100,20:200)
|
||||
- nr_months: how many months is recurring
|
||||
|
||||
if currency not specified then is always in USD
|
||||
|
||||
```js
|
||||
|
||||
!!bizmodel.revenue_recurring_define bizname:'test'
|
||||
name: '3node_lic'
|
||||
descr:'3NODE License Sales Recurring Basic'
|
||||
revenue_setup:'1:100,60:50'
|
||||
// revenue_setup:'5'
|
||||
revenue_monthly_delay:3
|
||||
revenue_monthly:'1:1,60:1'
|
||||
// cogs_setup:'1:0'
|
||||
cogs_setup_perc:'50%'
|
||||
revenue_setup_delay:1
|
||||
cogs_monthly_perc:'50%'
|
||||
nr_sold:'10:1000,24:2000,60:40000'
|
||||
60 is the default
|
||||
nr_months:60
|
||||
```
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
@@ -1 +0,0 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
@@ -1,15 +0,0 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.sysadmintools.daguserver
|
||||
import freeflowuniverse.herolib.installers.infra.zinit
|
||||
|
||||
// make sure zinit is there and running, will restart it if needed
|
||||
mut z := zinit.get()!
|
||||
z.destroy()!
|
||||
z.start()!
|
||||
|
||||
// mut ds := daguserver.get()!
|
||||
// ds.destroy()!
|
||||
// ds.start()!
|
||||
|
||||
// println(ds)
|
||||
8
examples/installers/db/meilisearch.vsh
Executable file
8
examples/installers/db/meilisearch.vsh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.db.meilisearch_installer
|
||||
|
||||
mut meilisearch := meilisearch_installer.get()!
|
||||
meilisearch.install()!
|
||||
meilisearch.start()!
|
||||
meilisearch.destroy()!
|
||||
9
examples/installers/db/postgresql.vsh
Executable file
9
examples/installers/db/postgresql.vsh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.db.postgresql as postgresql_installer
|
||||
|
||||
mut db := postgresql_installer.get()!
|
||||
|
||||
db.install()!
|
||||
db.start()!
|
||||
db.destroy()!
|
||||
9
examples/installers/db/zerodb.vsh
Executable file
9
examples/installers/db/zerodb.vsh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.db.zerodb as zerodb_installer
|
||||
|
||||
mut db := zerodb_installer.get()!
|
||||
|
||||
db.install()!
|
||||
db.start()!
|
||||
db.destroy()!
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.infra.gitea as gitea_installer
|
||||
|
||||
mut installer := gitea_installer.get(name: 'test')!
|
||||
|
||||
// if you want to configure using heroscript
|
||||
gitea_installer.play(
|
||||
heroscript: "
|
||||
!!gitea.configure name:test
|
||||
passwd:'something'
|
||||
domain: 'docs.info.com'
|
||||
"
|
||||
)!
|
||||
|
||||
installer.start()!
|
||||
8
examples/installers/infra/gitea.vsh
Executable file
8
examples/installers/infra/gitea.vsh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.infra.gitea as gitea_installer
|
||||
|
||||
mut gitea := gitea_installer.get()!
|
||||
gitea.install()!
|
||||
gitea.start()!
|
||||
gitea.destroy()!
|
||||
8
examples/installers/infra/livekit.vsh
Executable file
8
examples/installers/infra/livekit.vsh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.infra.livekit as livekit_installer
|
||||
|
||||
mut livekit := livekit_installer.get()!
|
||||
livekit.install()!
|
||||
livekit.start()!
|
||||
livekit.destroy()!
|
||||
8
examples/installers/infra/screen.vsh
Executable file
8
examples/installers/infra/screen.vsh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.infra.screen as screen_installer
|
||||
|
||||
mut screen := screen_installer.get()!
|
||||
|
||||
screen.install()!
|
||||
screen.destroy()!
|
||||
@@ -1,6 +1,8 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.sysadmintools.zinit as zinit_installer
|
||||
import freeflowuniverse.herolib.installers.infra.zinit_installer
|
||||
|
||||
mut installer := zinit_installer.get()!
|
||||
installer.install()!
|
||||
installer.start()!
|
||||
// installer.destroy()!
|
||||
6
examples/installers/lang/golang.vsh
Executable file
6
examples/installers/lang/golang.vsh
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.lang.golang
|
||||
|
||||
mut golang_installer := golang.get()!
|
||||
golang_installer.install()!
|
||||
7
examples/installers/lang/nodejs.vsh
Executable file
7
examples/installers/lang/nodejs.vsh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.lang.nodejs
|
||||
|
||||
mut nodejs_installer := nodejs.get()!
|
||||
// nodejs_installer.install()!
|
||||
nodejs_installer.destroy()!
|
||||
7
examples/installers/lang/python.vsh
Executable file
7
examples/installers/lang/python.vsh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.lang.python as python_module
|
||||
|
||||
mut python_installer := python_module.get()!
|
||||
// python_installer.install()!
|
||||
python_installer.destroy()!
|
||||
7
examples/installers/lang/rust.vsh
Executable file
7
examples/installers/lang/rust.vsh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.lang.rust as rust_module
|
||||
|
||||
mut rust_installer := rust_module.get()!
|
||||
// rust_installer.install()!
|
||||
rust_installer.destroy()!
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.net.mycelium as mycelium_installer
|
||||
import freeflowuniverse.herolib.installers.net.mycelium_installer
|
||||
import freeflowuniverse.herolib.clients.mycelium
|
||||
|
||||
mut installer := mycelium_installer.get()!
|
||||
@@ -13,25 +13,27 @@ mut client := mycelium.get()!
|
||||
|
||||
// Send a message to a node by public key
|
||||
// Parameters: public_key, payload, topic, wait_for_reply
|
||||
msg := client.send_msg('abc123...', // destination public key
|
||||
'Hello World', // message payload
|
||||
'greetings', // optional topic
|
||||
true // wait for reply
|
||||
)!
|
||||
msg := client.send_msg(
|
||||
public_key: 'abc123...' // destination public key
|
||||
payload: 'Hello World' // message payload
|
||||
topic: 'greetings' // optional topic
|
||||
wait: true // wait for reply
|
||||
)!
|
||||
println('Sent message ID: ${msg.id}')
|
||||
|
||||
// Receive messages
|
||||
// Parameters: wait_for_message, peek_only, topic_filter
|
||||
received := client.receive_msg(true, false, 'greetings')!
|
||||
received := client.receive_msg(wait: true, peek: false, topic: 'greetings')!
|
||||
println('Received message from: ${received.src_pk}')
|
||||
println('Message payload: ${received.payload}')
|
||||
|
||||
// Reply to a message
|
||||
client.reply_msg(received.id, // original message ID
|
||||
received.src_pk, // sender's public key
|
||||
'Got your message!', // reply payload
|
||||
'greetings' // topic
|
||||
)!
|
||||
client.reply_msg(
|
||||
id: received.id // original message ID
|
||||
public_key: received.src_pk // sender's public key
|
||||
payload: 'Got your message!' // reply payload
|
||||
topic: 'greetings' // topic
|
||||
)!
|
||||
|
||||
// Check message status
|
||||
status := client.get_msg_status(msg.id)!
|
||||
7
examples/installers/net/wireguard.vsh
Executable file
7
examples/installers/net/wireguard.vsh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.net.wireguard_installer as wireguard
|
||||
|
||||
mut wireguard_installer := wireguard.get()!
|
||||
wireguard_installer.install()!
|
||||
wireguard_installer.destroy()!
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import time
|
||||
import freeflowuniverse.herolib.installers.db.postgresql
|
||||
|
||||
mut db := postgresql.get()!
|
||||
|
||||
// db.destroy()!
|
||||
db.start()!
|
||||
|
||||
// db.db_create('my_new_db')!
|
||||
// db.stop()!
|
||||
// db.start()!
|
||||
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.sysadmintools.actrunner
|
||||
import freeflowuniverse.herolib.installers.virt.herocontainers
|
||||
// import freeflowuniverse.herolib.installers.virt.herocontainers
|
||||
|
||||
actrunner.install()!
|
||||
mut actrunner_ := actrunner.get()!
|
||||
actrunner_.install()!
|
||||
// herocontainers.start()!
|
||||
8
examples/installers/sysadmintools/garage_s3.vsh
Executable file
8
examples/installers/sysadmintools/garage_s3.vsh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.sysadmintools.garage_s3 as garage_s3_installer
|
||||
|
||||
mut garage_s3 := garage_s3_installer.get()!
|
||||
garage_s3.install()!
|
||||
garage_s3.start()!
|
||||
garage_s3.destroy()!
|
||||
7
examples/installers/sysadmintools/rclone.vsh
Executable file
7
examples/installers/sysadmintools/rclone.vsh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.sysadmintools.rclone as rclone_installer
|
||||
|
||||
mut rclone := rclone_installer.get()!
|
||||
rclone.install()!
|
||||
rclone.destroy()!
|
||||
@@ -4,3 +4,4 @@ import freeflowuniverse.herolib.installers.threefold.griddriver
|
||||
|
||||
mut griddriver_installer := griddriver.get()!
|
||||
griddriver_installer.install()!
|
||||
griddriver_installer.destroy()!
|
||||
9
examples/installers/virt/dagu.vsh
Executable file
9
examples/installers/virt/dagu.vsh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.sysadmintools.daguserver
|
||||
import freeflowuniverse.herolib.installers.infra.zinit_installer
|
||||
|
||||
mut ds := daguserver.get()!
|
||||
ds.install()!
|
||||
ds.start()!
|
||||
ds.destroy()!
|
||||
11
examples/installers/virt/pacman.vsh
Executable file
11
examples/installers/virt/pacman.vsh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.virt.pacman as pacman_installer
|
||||
|
||||
mut pacman := pacman_installer.get()!
|
||||
|
||||
// To install
|
||||
pacman.install()!
|
||||
|
||||
// To remove
|
||||
pacman.destroy()!
|
||||
60
examples/osal/coredns/example.vsh
Executable file
60
examples/osal/coredns/example.vsh
Executable file
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env -S v -n -w -cg -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.installers.infra.coredns as coredns_installer
|
||||
import freeflowuniverse.herolib.osal.coredns
|
||||
import freeflowuniverse.herolib.core.playbook
|
||||
|
||||
// coredns_installer.delete()!
|
||||
mut installer := coredns_installer.get()!
|
||||
// coredns_installer.fix()!
|
||||
installer.start()!
|
||||
|
||||
mut script := "
|
||||
!!dns.a_record
|
||||
sub_domain: 'host1'
|
||||
ip: '1.2.3.4'
|
||||
ttl: 300
|
||||
|
||||
!!dns.aaaa_record
|
||||
sub_domain: 'host1'
|
||||
ip: '2001:db8::1'
|
||||
ttl: 300
|
||||
|
||||
!!dns.mx_record
|
||||
sub_domain: '*'
|
||||
host: 'mail.example.com'
|
||||
preference: 10
|
||||
ttl: 300
|
||||
|
||||
!!dns.txt_record
|
||||
sub_domain: '*'
|
||||
text: 'v=spf1 mx ~all'
|
||||
ttl: 300
|
||||
|
||||
!!dns.srv_record
|
||||
service: 'ssh'
|
||||
protocol: 'tcp'
|
||||
host: 'host1'
|
||||
target: 'sip.example.com'
|
||||
port: 5060
|
||||
priority: 10
|
||||
weight: 100
|
||||
ttl: 300
|
||||
|
||||
!!dns.ns_record
|
||||
host: 'ns1.example.com'
|
||||
ttl: 300
|
||||
|
||||
!!dns.soa_record
|
||||
mbox: 'hostmaster.example.com'
|
||||
ns: 'ns1.example.com'
|
||||
refresh: 44
|
||||
retry: 55
|
||||
expire: 66
|
||||
minttl: 100
|
||||
ttl: 300
|
||||
"
|
||||
|
||||
mut plbook := playbook.new(text: script)!
|
||||
mut set := coredns.play_dns(mut plbook)!
|
||||
set.set(key_prefix: 'dns:', domain: 'heroexample.com')!
|
||||
@@ -1,6 +1,5 @@
|
||||
#!/usr/bin/env -S v -gc none -no-retry-compilation -d use_openssl -enable-globals -cg run
|
||||
|
||||
//#!/usr/bin/env -S v -gc none -no-retry-compilation -cc tcc -d use_openssl -enable-globals -cg run
|
||||
import freeflowuniverse.herolib.threefold.gridproxy
|
||||
import freeflowuniverse.herolib.threefold.tfgrid3deployer
|
||||
import freeflowuniverse.herolib.installers.threefold.griddriver
|
||||
@@ -20,7 +19,8 @@ deployment.add_machine(
|
||||
cpu: 1
|
||||
memory: 2
|
||||
planetary: false
|
||||
public_ip4: true
|
||||
wireguard: true
|
||||
public_ip4: false
|
||||
size: 10 // 10 gig
|
||||
mycelium: tfgrid3deployer.Mycelium{}
|
||||
)
|
||||
|
||||
@@ -3,10 +3,8 @@
|
||||
import freeflowuniverse.herolib.threefold.gridproxy
|
||||
import freeflowuniverse.herolib.threefold.tfgrid3deployer
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.installers.threefold.griddriver
|
||||
|
||||
fn main() {
|
||||
griddriver.install()!
|
||||
|
||||
v := tfgrid3deployer.get()!
|
||||
println('cred: ${v}')
|
||||
@@ -19,19 +17,19 @@ fn main() {
|
||||
cpu: 1
|
||||
memory: 2
|
||||
planetary: false
|
||||
public_ip4: true
|
||||
public_ip4: false
|
||||
mycelium: tfgrid3deployer.Mycelium{}
|
||||
nodes: [u32(167)]
|
||||
)
|
||||
deployment.add_machine(
|
||||
name: 'my_vm2'
|
||||
cpu: 1
|
||||
memory: 2
|
||||
planetary: false
|
||||
public_ip4: true
|
||||
mycelium: tfgrid3deployer.Mycelium{}
|
||||
// nodes: [u32(164)]
|
||||
)
|
||||
// deployment.add_machine(
|
||||
// name: 'my_vm2'
|
||||
// cpu: 1
|
||||
// memory: 2
|
||||
// planetary: false
|
||||
// public_ip4: true
|
||||
// mycelium: tfgrid3deployer.Mycelium{}
|
||||
// // nodes: [u32(164)]
|
||||
// )
|
||||
|
||||
deployment.add_zdb(name: 'my_zdb', password: 'my_passw&rd', size: 2)
|
||||
deployment.add_webname(name: 'mywebname2', backend: 'http://37.27.132.47:8000')
|
||||
|
||||
@@ -7,7 +7,10 @@ import freeflowuniverse.herolib.installers.threefold.griddriver
|
||||
import os
|
||||
import time
|
||||
|
||||
griddriver.install()!
|
||||
|
||||
res2:=tfgrid3deployer.filter_nodes()!
|
||||
println(res2)
|
||||
exit(0)
|
||||
|
||||
v := tfgrid3deployer.get()!
|
||||
println('cred: ${v}')
|
||||
@@ -18,7 +21,7 @@ deployment.add_machine(
|
||||
cpu: 1
|
||||
memory: 2
|
||||
planetary: false
|
||||
public_ip4: true
|
||||
public_ip4: false
|
||||
size: 10 // 10 gig
|
||||
mycelium: tfgrid3deployer.Mycelium{}
|
||||
)
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cg -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.web.docusaurus
|
||||
// import freeflowuniverse.herolib.data.doctree
|
||||
|
||||
// Create a new docusaurus factory
|
||||
mut docs := docusaurus.new(
|
||||
build_path: '/tmp/docusaurus_build'
|
||||
)!
|
||||
|
||||
// Create a new docusaurus site
|
||||
mut site := docs.dev(
|
||||
url: 'https://git.ourworld.tf/despiegk/docs_kristof'
|
||||
)!
|
||||
|
||||
// FOR FUTURE TO ADD CONTENT FROM DOCTREE
|
||||
|
||||
// Create a doctree for content
|
||||
// mut tree := doctree.new(name: 'content')!
|
||||
|
||||
// // Add some content from a git repository
|
||||
// tree.scan(
|
||||
// git_url: 'https://github.com/yourusername/your-docs-repo'
|
||||
// git_pull: true
|
||||
// )!
|
||||
|
||||
// // Export the content to the docusaurus site
|
||||
// tree.export(
|
||||
// destination: '${site.path_build.path}/docs'
|
||||
// reset: true
|
||||
// keep_structure: true
|
||||
// exclude_errors: false
|
||||
// )!
|
||||
|
||||
// Build the docusaurus site
|
||||
// site.build()!
|
||||
|
||||
// Generate the static site
|
||||
// site.generate()!
|
||||
|
||||
// Optionally open the site in a browser
|
||||
// site.open()!
|
||||
94
examples/webtools/markdown_renderer/markdown_parser.vsh
Executable file
94
examples/webtools/markdown_renderer/markdown_parser.vsh
Executable file
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none run
|
||||
|
||||
import freeflowuniverse.herolib.data.markdownparser2
|
||||
|
||||
// Sample markdown text
|
||||
text := '# Heading 1
|
||||
|
||||
This is a paragraph with **bold** and *italic* text.
|
||||
|
||||
## Heading 2
|
||||
|
||||
- List item 1
|
||||
- List item 2
|
||||
- Nested item
|
||||
- List item 3
|
||||
|
||||
```v
|
||||
fn main() {
|
||||
println("Hello, world!")
|
||||
}
|
||||
```
|
||||
|
||||
> This is a blockquote
|
||||
> with multiple lines
|
||||
|
||||
| Column 1 | Column 2 | Column 3 |
|
||||
|----------|:--------:|---------:|
|
||||
| Left | Center | Right |
|
||||
| Cell 1 | Cell 2 | Cell 3 |
|
||||
|
||||
[Link to V language](https://vlang.io)
|
||||
|
||||

|
||||
|
||||
Footnote reference[^1]
|
||||
|
||||
[^1]: This is a footnote.
|
||||
'
|
||||
|
||||
// Example 1: Using the plain text renderer
|
||||
println('=== PLAINTEXT RENDERING ===')
|
||||
println(markdownparser2.to_plain(text))
|
||||
println('')
|
||||
|
||||
// Example 2: Using the structure renderer to show markdown structure
|
||||
println('=== STRUCTURE RENDERING ===')
|
||||
println(markdownparser2.to_structure(text))
|
||||
|
||||
// Example 3: Using the navigator to find specific elements
|
||||
println('\n=== NAVIGATION EXAMPLE ===')
|
||||
|
||||
// Parse the markdown text
|
||||
doc := markdownparser2.parse(text)
|
||||
|
||||
// Create a navigator
|
||||
mut nav := markdownparser2.new_navigator(doc)
|
||||
|
||||
// Find all headings
|
||||
headings := nav.find_all_by_type(.heading)
|
||||
println('Found ${headings.len} headings:')
|
||||
for heading in headings {
|
||||
level := heading.attributes['level']
|
||||
println(' ${'#'.repeat(level.int())} ${heading.content}')
|
||||
}
|
||||
|
||||
// Find all code blocks
|
||||
code_blocks := nav.find_all_by_type(.code_block)
|
||||
println('\nFound ${code_blocks.len} code blocks:')
|
||||
for block in code_blocks {
|
||||
language := block.attributes['language']
|
||||
println(' Language: ${language}')
|
||||
println(' Content length: ${block.content.len} characters')
|
||||
}
|
||||
|
||||
// Find all list items
|
||||
list_items := nav.find_all_by_type(.list_item)
|
||||
println('\nFound ${list_items.len} list items:')
|
||||
for item in list_items {
|
||||
println(' - ${item.content}')
|
||||
}
|
||||
|
||||
// Find content containing specific text
|
||||
if element := nav.find_by_content('blockquote') {
|
||||
println('\nFound element containing "blockquote":')
|
||||
println(' Type: ${element.typ}')
|
||||
println(' Content: ${element.content}')
|
||||
}
|
||||
|
||||
// Find all footnotes
|
||||
println('\nFootnotes:')
|
||||
for id, footnote in nav.footnotes() {
|
||||
println(' [^${id}]: ${footnote.content}')
|
||||
}
|
||||
|
||||
27
examples/webtools/markdown_renderer/markdown_render.vsh
Executable file
27
examples/webtools/markdown_renderer/markdown_render.vsh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
// import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import log
|
||||
import os
|
||||
import markdown
|
||||
import freeflowuniverse.herolib.data.markdownparser2
|
||||
|
||||
path2:="${os.home_dir()}/code/github/freeflowuniverse/herolib/examples/webtools/mdbook_markdown/content/links.md"
|
||||
path1:="${os.home_dir()}/code/github/freeflowuniverse/herolib/examples/webtools/mdbook_markdown/content/test.md"
|
||||
|
||||
text := os.read_file(path1)!
|
||||
|
||||
// Example 1: Using the built-in plaintext renderer
|
||||
println('=== PLAINTEXT RENDERING ===')
|
||||
println(markdown.to_plain(text))
|
||||
println('')
|
||||
|
||||
// Example 2: Using our custom structure renderer to show markdown structure
|
||||
println('=== STRUCTURE RENDERING ===')
|
||||
println(markdownparser2.to_structure(text))
|
||||
|
||||
// // Example 3: Using a simple markdown example to demonstrate structure
|
||||
// println('\n=== STRUCTURE OF A SIMPLE MARKDOWN EXAMPLE ===')
|
||||
// simple_md := '# Heading 1\n\nThis is a paragraph with **bold** and *italic* text.\n\n- List item 1\n- List item 2\n\n```v\nfn main() {\n\tprintln("Hello, world!")\n}\n```\n\n[Link to V language](https://vlang.io)'
|
||||
// println(markdown.to_structure(simple_md))
|
||||
29
examples/webtools/mdbook_markdown/content/cybercity.md
Normal file
29
examples/webtools/mdbook_markdown/content/cybercity.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
sidebar_position: 10
|
||||
title: 'Dunia CyberCity'
|
||||
description: 'Co-create the Future'
|
||||
---
|
||||
|
||||

|
||||
|
||||
|
||||
We are building a 700,000 m2 Regenerative Startup Cyber City
|
||||
|
||||
- 100% co-owned
|
||||
- regenerative
|
||||
- autonomous zone
|
||||
|
||||
a city for startups and its creators
|
||||
|
||||
- build a system for augmented collective intelligence
|
||||
- operate business wise from a digital freezone
|
||||
- (co)own assets (shares, digital currencies) safely and privately
|
||||
|
||||
|
||||
## More Info
|
||||
|
||||
> see [https://friends.threefold.info/cybercity](https://friends.threefold.info/cybercity)
|
||||
|
||||
- login:```planet```
|
||||
- passwd:```first```
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.data.doctree
|
||||
|
||||
@@ -11,16 +11,17 @@ mut tree := doctree.new(name: 'test')!
|
||||
// git_root string
|
||||
// git_pull bool
|
||||
// load bool = true // means we scan automatically the added collection
|
||||
for project in 'projectinca, legal, why, web4,tfgrid3'.split(',').map(it.trim_space()) {
|
||||
for project in 'projectinca, legal, why'.split(',').map(it.trim_space()) {
|
||||
tree.scan(
|
||||
git_url: 'https://git.ourworld.tf/tfgrid/info_tfgrid/src/branch/development/collections/${project}'
|
||||
git_pull: false
|
||||
)!
|
||||
}
|
||||
|
||||
|
||||
tree.export(
|
||||
destination: '/tmp/test'
|
||||
destination: '/tmp/mdexport'
|
||||
reset: true
|
||||
keep_structure: true
|
||||
//keep_structure: true
|
||||
exclude_errors: false
|
||||
)!
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
// import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
|
||||
17
examples/webtools/starllight_example.vsh
Executable file
17
examples/webtools/starllight_example.vsh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env -S v -n -w -gc none -cg -cc tcc -d use_openssl -enable-globals run
|
||||
|
||||
import freeflowuniverse.herolib.web.starlight
|
||||
// import freeflowuniverse.herolib.data.doctree
|
||||
|
||||
// Create a new starlight factory
|
||||
mut docs := starlight.new(
|
||||
build_path: '/tmp/starlight_build'
|
||||
)!
|
||||
|
||||
// Create a new starlight site
|
||||
mut site := docs.get(
|
||||
url: 'https://git.ourworld.tf/tfgrid/docs_aibox'
|
||||
init:true //init means we put config files if not there
|
||||
)!
|
||||
|
||||
site.dev()!
|
||||
@@ -4,7 +4,7 @@ set -e
|
||||
|
||||
os_name="$(uname -s)"
|
||||
arch_name="$(uname -m)"
|
||||
version='1.0.13'
|
||||
version='1.0.21'
|
||||
|
||||
|
||||
# Base URL for GitHub releases
|
||||
|
||||
@@ -181,7 +181,7 @@ function os_update {
|
||||
fi
|
||||
#apt install apt-transport-https ca-certificates curl software-properties-common -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" --force-yes
|
||||
package_install "apt-transport-https ca-certificates curl wget software-properties-common tmux"
|
||||
package_install "rclone rsync mc redis-server screen net-tools git dnsutils htop ca-certificates screen lsb-release binutils pkg-config"
|
||||
package_install "rclone rsync mc redis-server screen net-tools git dnsutils htop ca-certificates screen lsb-release binutils pkg-config libssl-dev iproute2"
|
||||
|
||||
elif [[ "${OSNAME}" == "darwin"* ]]; then
|
||||
if command -v brew >/dev/null 2>&1; then
|
||||
|
||||
1
lib/biz/bizmodel/.gitignore
vendored
Normal file
1
lib/biz/bizmodel/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
testdata
|
||||
155
lib/biz/bizmodel/act.v
Normal file
155
lib/biz/bizmodel/act.v
Normal file
@@ -0,0 +1,155 @@
|
||||
module bizmodel
|
||||
|
||||
import os
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
import freeflowuniverse.herolib.core.playbook { PlayBook, Action }
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
// import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.data.paramsparser {Params}
|
||||
import freeflowuniverse.herolib.biz.spreadsheet {RowGetArgs, UnitType, PeriodType}
|
||||
|
||||
pub fn (mut m BizModel) act(action Action) !Action {
|
||||
return match texttools.snake_case(action.name) {
|
||||
'funding_define' {
|
||||
m.funding_define_action(action)!
|
||||
}
|
||||
'revenue_define' {
|
||||
m.revenue_action(action)!
|
||||
}
|
||||
'costcenter_define' {
|
||||
m.costcenter_define_action(action)!
|
||||
}
|
||||
'cost_define' {
|
||||
m.cost_define_action(action)!
|
||||
}
|
||||
'department_define' {
|
||||
m.department_define_action(action)!
|
||||
}
|
||||
'employee_define' {
|
||||
m.employee_define_action(action)!
|
||||
}
|
||||
'export_report' {
|
||||
m.new_report_action(action)!
|
||||
}
|
||||
'sheet_wiki' {
|
||||
m.export_sheet_action(action)!
|
||||
}
|
||||
'graph_bar_row' {
|
||||
m.export_graph_bar_action(action)!
|
||||
}
|
||||
'graph_pie_row' {
|
||||
m.export_graph_pie_action(action)!
|
||||
}
|
||||
'graph_line_row' {
|
||||
m.export_graph_line_action(action)!
|
||||
}
|
||||
'row_overview' {
|
||||
m.export_overview_action(action)!
|
||||
}
|
||||
else {
|
||||
return error('Unknown operation: ${action.name}')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut m BizModel) export_sheet_action(action Action) !Action {
|
||||
return m.export_action(m.sheet.wiki(row_args_from_params(action.params)!)!, action)
|
||||
}
|
||||
|
||||
fn (mut m BizModel) export_graph_title_action(action Action) !Action {
|
||||
return m.export_action(m.sheet.wiki_title_chart(row_args_from_params(action.params)!)!, action)
|
||||
}
|
||||
|
||||
fn (mut m BizModel) export_graph_line_action(action Action) !Action {
|
||||
return m.export_action(m.sheet.wiki_line_chart(row_args_from_params(action.params)!)!, action)
|
||||
}
|
||||
|
||||
fn (mut m BizModel) export_graph_bar_action(action Action) !Action {
|
||||
return m.export_action(m.sheet.wiki_bar_chart(row_args_from_params(action.params)!)!, action)
|
||||
}
|
||||
|
||||
pub fn (mut m BizModel) export_graph_pie_action(action Action) !Action {
|
||||
return m.export_action(m.sheet.wiki_pie_chart(row_args_from_params(action.params)!)!, action)
|
||||
}
|
||||
|
||||
pub fn (mut m BizModel) export_overview_action(action Action) !Action {
|
||||
return m.export_action(m.sheet.wiki_row_overview(row_args_from_params(action.params)!)!, action)
|
||||
}
|
||||
|
||||
fn (mut m BizModel) new_report_action(action Action) !Action {
|
||||
m.new_report(action.params.decode[Report]()!)!
|
||||
return action
|
||||
}
|
||||
|
||||
// fetches args for getting row from params
|
||||
pub fn row_args_from_params(p Params) !RowGetArgs {
|
||||
rowname := p.get_default('rowname', '')!
|
||||
namefilter := p.get_list_default('namefilter', [])!
|
||||
includefilter := p.get_list_default('includefilter', [])!
|
||||
excludefilter := p.get_list_default('excludefilter', [])!
|
||||
size := p.get_default('size', '')!
|
||||
title_sub := p.get_default('title_sub', '')!
|
||||
title := p.get_default('title', '')!
|
||||
unit := p.get_default('unit', 'normal')!
|
||||
unit_e := match unit {
|
||||
'thousand' { UnitType.thousand }
|
||||
'million' { UnitType.million }
|
||||
'billion' { UnitType.billion }
|
||||
else { UnitType.normal }
|
||||
}
|
||||
period_type := p.get_default('period_type', 'year')!
|
||||
if period_type !in ['year', 'month', 'quarter'] {
|
||||
return error('period type needs to be in year,month,quarter')
|
||||
}
|
||||
period_type_e := match period_type {
|
||||
'year' { PeriodType.year }
|
||||
'month' { PeriodType.month }
|
||||
'quarter' { PeriodType.quarter }
|
||||
else { PeriodType.error }
|
||||
}
|
||||
if period_type_e == .error {
|
||||
return error('period type needs to be in year,month,quarter')
|
||||
}
|
||||
|
||||
rowname_show := p.get_default_true('rowname_show')
|
||||
descr_show := p.get_default_true('descr_show')
|
||||
|
||||
return RowGetArgs{
|
||||
rowname: rowname
|
||||
namefilter: namefilter
|
||||
includefilter: includefilter
|
||||
excludefilter: excludefilter
|
||||
period_type: period_type_e
|
||||
unit: unit_e
|
||||
title_sub: title_sub
|
||||
title: title
|
||||
size: size
|
||||
rowname_show: rowname_show
|
||||
descr_show: descr_show
|
||||
}
|
||||
}
|
||||
|
||||
// creates the name for a file being exported given the params of the export action
|
||||
fn (m BizModel) export_action(content string, action Action) !Action {
|
||||
// determine name of file being exported
|
||||
name := if action.params.exists('name') { action.params.get('name')! } else {
|
||||
if action.params.exists('title') { action.params.get('title')! } else {
|
||||
// if no name or title, name is ex: revenue_total_graph_bar_row
|
||||
rowname := action.params.get_default('rowname', '')!
|
||||
'${rowname}_${action.name}'
|
||||
}
|
||||
}
|
||||
|
||||
// by default exports to working dir of bizmodel
|
||||
destination := action.params.get_default('destination', m.workdir)!
|
||||
|
||||
mut path := pathlib.get_file(
|
||||
path: os.join_path(destination, name)
|
||||
increment: true
|
||||
empty: action.params.get_default_false('overwrite')
|
||||
)!
|
||||
|
||||
path.write(content)!
|
||||
return action
|
||||
}
|
||||
151
lib/biz/bizmodel/export.v
Normal file
151
lib/biz/bizmodel/export.v
Normal file
@@ -0,0 +1,151 @@
|
||||
module bizmodel
|
||||
|
||||
import os
|
||||
import freeflowuniverse.herolib.web.docusaurus
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
|
||||
pub struct Report {
|
||||
pub:
|
||||
name string
|
||||
title string
|
||||
description string
|
||||
path string
|
||||
sections []ReportSection
|
||||
}
|
||||
|
||||
pub enum ReportSection {
|
||||
revenue_model
|
||||
cost_structure
|
||||
human_resources
|
||||
}
|
||||
|
||||
pub fn (b BizModel) new_report(report Report) !Report {
|
||||
name := if report.name != '' {report.name} else { texttools.snake_case(report.title) }
|
||||
path := pathlib.get_dir(
|
||||
path: os.join_path(os.home_dir(), '/hero/var/bizmodel/reports/${name}')
|
||||
create: true
|
||||
empty: true
|
||||
)!
|
||||
|
||||
b.write_introduction(path.path)!
|
||||
b.write_operational_plan(path.path)!
|
||||
b.write_revenue_model(path.path)!
|
||||
b.write_cost_structure(path.path)!
|
||||
|
||||
return Report {
|
||||
...report,
|
||||
name: name
|
||||
path: path.path
|
||||
}
|
||||
// b.export_summary()
|
||||
// b.export_business_description()
|
||||
// b.export_market_analysis()
|
||||
// b.export_business_model()
|
||||
// b.export_revenue_model(export)!
|
||||
// b.export_cost_structure(export)
|
||||
// b.export_operational_plan(export)!
|
||||
// b.export_fundraising(export)
|
||||
}
|
||||
|
||||
pub struct Export {
|
||||
pub:
|
||||
path string
|
||||
overwrite bool
|
||||
format ExportFormat
|
||||
}
|
||||
|
||||
pub enum ExportFormat {
|
||||
docusaurus
|
||||
mdbook
|
||||
}
|
||||
|
||||
pub fn (r Report) export(export Export) ! {
|
||||
match export.format {
|
||||
.docusaurus {
|
||||
mut dir := pathlib.get_dir(path: r.path)!
|
||||
dir.copy(dest: '${export.path}/docs', delete: true)!
|
||||
mut factory := docusaurus.new()!
|
||||
mut site := factory.get(
|
||||
name: r.name
|
||||
path: export.path
|
||||
publish_path: export.path
|
||||
init: true
|
||||
config: docusaurus.Config {
|
||||
navbar: docusaurus.Navbar {
|
||||
title: "Business Model",
|
||||
items: [
|
||||
docusaurus.NavbarItem{
|
||||
"href": "https://threefold.info/kristof/",
|
||||
"label": "ThreeFold Technology",
|
||||
"position": "right"
|
||||
},
|
||||
docusaurus.NavbarItem{
|
||||
"href": "https://threefold.io",
|
||||
"label": "Operational Plan",
|
||||
"position": "left"
|
||||
}
|
||||
]
|
||||
}
|
||||
main: docusaurus.Main {
|
||||
url_home: 'docs/introduction'
|
||||
}
|
||||
} //TODO: is this needed
|
||||
)!
|
||||
site.generate()!
|
||||
}
|
||||
.mdbook {panic('MDBook export not fully implemented')}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (model BizModel) write_introduction(path string) ! {
|
||||
mut index_page := pathlib.get_file(path: '${path}/introduction.md')!
|
||||
// mut tmpl_index := $tmpl('templates/index.md')
|
||||
index_page.template_write($tmpl('templates/introduction.md'), true)!
|
||||
}
|
||||
|
||||
pub fn (model BizModel) write_operational_plan(path string) ! {
|
||||
mut dir := pathlib.get_dir(path: '${path}/operational_plan')!
|
||||
mut ops_page := pathlib.get_file(path: '${dir.path}/operational_plan.md')!
|
||||
ops_page.write('# Operational Plan')!
|
||||
|
||||
mut hr_dir := pathlib.get_dir(path: '${dir.path}/human_resources')!
|
||||
mut hr_page := pathlib.get_file(path: '${hr_dir.path}/human_resources.md')!
|
||||
hr_page.template_write($tmpl('./templates/human_resources.md'), true)!
|
||||
|
||||
for key, employee in model.employees {
|
||||
mut employee_page := pathlib.get_file(path: '${hr_dir.path}/${texttools.snake_case(employee.name)}.md')!
|
||||
employee_cost_chart := model.sheet.line_chart(rowname:'hr_cost_${employee.name}', unit: .million)!.mdx()
|
||||
employee_page.template_write($tmpl('./templates/employee.md'), true)!
|
||||
}
|
||||
|
||||
mut depts_dir := pathlib.get_dir(path: '${dir.path}/departments')!
|
||||
for key, department in model.departments {
|
||||
mut dept_page := pathlib.get_file(path: '${depts_dir.path}/${texttools.snake_case(department.name)}.md')!
|
||||
// dept_cost_chart := model.sheet.line_chart(rowname:'hr_cost_${employee.name}', unit: .million)!.mdx()
|
||||
// println(employee_cost_chart)
|
||||
dept_page.template_write($tmpl('./templates/department.md'), true)!
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (model BizModel) write_revenue_model(path string) ! {
|
||||
mut dir := pathlib.get_dir(path: '${path}/revenue_model')!
|
||||
mut rm_page := pathlib.get_file(path: '${dir.path}/revenue_model.md')!
|
||||
rm_page.write('# Revenue Model')!
|
||||
|
||||
mut products_dir := pathlib.get_dir(path: '${dir.path}/products')!
|
||||
mut products_page := pathlib.get_file(path: '${products_dir.path}/products.md')!
|
||||
products_page.template_write('# Products', true)!
|
||||
|
||||
name1 := 'example'
|
||||
for key, product in model.products {
|
||||
mut product_page := pathlib.get_file(path: '${products_dir.path}/${texttools.snake_case(product.name)}.md')!
|
||||
product_page.template_write($tmpl('./templates/product.md'), true)!
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (model BizModel) write_cost_structure(path string) ! {
|
||||
mut dir := pathlib.get_dir(path: '${path}/cost_structure')!
|
||||
mut cs_page := pathlib.get_file(path: '${dir.path}/cost_structure.md')!
|
||||
cs_page.write('# Cost Structure')!
|
||||
}
|
||||
14
lib/biz/bizmodel/export_test.v
Normal file
14
lib/biz/bizmodel/export_test.v
Normal file
@@ -0,0 +1,14 @@
|
||||
module bizmodel
|
||||
|
||||
import os
|
||||
import freeflowuniverse.herolib.web.docusaurus
|
||||
|
||||
const bizmodel_name = 'test'
|
||||
const export_path = os.join_path(os.dir(@FILE), 'testdata')
|
||||
|
||||
pub fn test_export_report() ! {
|
||||
model := getset(bizmodel_name)!
|
||||
model.export_report(Report{
|
||||
title: 'My Business Model'
|
||||
}, path: export_path)!
|
||||
}
|
||||
@@ -11,8 +11,8 @@ pub fn get(name string) !&BizModel {
|
||||
if name in bizmodels {
|
||||
return bizmodels[name] or { panic('bug') }
|
||||
}
|
||||
return error("cann't find biz model:'${name}' in global bizmodels ${bizmodels.keys()}")
|
||||
}
|
||||
return error("cann't find biz model:'${name}' in global bizmodels")
|
||||
}
|
||||
|
||||
// get bizmodel from global
|
||||
|
||||
@@ -62,7 +62,7 @@ fn employee_wiki(p paramsparser.Params, sim BizModel) !string {
|
||||
|
||||
// theme := 'light'
|
||||
// theme := 'dark' // Removed unused variable
|
||||
mut t := $tmpl('./templates/employee.md')
|
||||
mut t := $tmpl('./templates/employee_old.md')
|
||||
return t
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
module bizmodel
|
||||
|
||||
import os
|
||||
import freeflowuniverse.herolib.biz.spreadsheet
|
||||
|
||||
pub struct BizModel {
|
||||
pub mut:
|
||||
name string
|
||||
description string
|
||||
workdir string = '${os.home_dir()}/hero/var/bizmodel'
|
||||
sheet &spreadsheet.Sheet
|
||||
employees map[string]&Employee
|
||||
departments map[string]&Department
|
||||
|
||||
@@ -1,89 +1,51 @@
|
||||
module bizmodel
|
||||
|
||||
import freeflowuniverse.herolib.core.playbook { PlayBook }
|
||||
import arrays
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
import freeflowuniverse.herolib.core.playbook { PlayBook, Action }
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
// import freeflowuniverse.herolib.core.texttools
|
||||
// import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.biz.spreadsheet
|
||||
|
||||
pub fn play(mut plbook PlayBook) ! {
|
||||
// first make sure we find a run action to know the name
|
||||
mut actions4 := plbook.actions_find(actor: 'bizmodel')!
|
||||
|
||||
if actions4.len == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
knownactions := ['revenue_define', 'employee_define', 'department_define', 'funding_define',
|
||||
'costcenter_define', 'cost_define']
|
||||
|
||||
for action in actions4 {
|
||||
// biz name needs to be specified in the the bizmodel hero actions
|
||||
bizname := action.params.get('bizname') or {
|
||||
return error("Can't find param: 'bizname' for ${action.actor}.${action.name} macro, is a requirement argument.")
|
||||
}
|
||||
mut sim := getset(bizname)!
|
||||
|
||||
if action.name !in knownactions {
|
||||
return error("Can't find macro with name: ${action.name} for macro's for bizmodel.")
|
||||
}
|
||||
|
||||
console.print_debug(action.name)
|
||||
match action.name {
|
||||
'revenue_define' {
|
||||
sim.revenue_action(action)!
|
||||
}
|
||||
'funding_define' {
|
||||
sim.funding_define_action(action)!
|
||||
}
|
||||
'costcenter_define' {
|
||||
sim.costcenter_define_action(action)!
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
|
||||
console.print_debug('TOTALS for bizmodel play')
|
||||
// now we have processed the macro's, we can calculate the totals
|
||||
rlock bizmodels {
|
||||
for _, mut sim in bizmodels {
|
||||
// sim.hr_total()!
|
||||
sim.cost_total()!
|
||||
sim.revenue_total()!
|
||||
sim.funding_total()!
|
||||
}
|
||||
}
|
||||
|
||||
for action in actions4 {
|
||||
console.print_debug(action.name)
|
||||
// biz name needs to be specified in the the bizmodel hero actions
|
||||
bizname := action.params.get('bizname') or {
|
||||
return error("Can't find param: 'bizname' for bizmodel macro, is a requirement argument.")
|
||||
}
|
||||
|
||||
mut sim := get(bizname)!
|
||||
|
||||
if action.name !in knownactions {
|
||||
return error("Can't find macro with name: ${action.name} for macro's for bizmodel.")
|
||||
}
|
||||
|
||||
match action.name {
|
||||
'cost_define' {
|
||||
sim.cost_define_action(action)!
|
||||
}
|
||||
'department_define' {
|
||||
sim.department_define_action(action)!
|
||||
}
|
||||
'employee_define' {
|
||||
sim.employee_define_action(action)!
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
|
||||
// mut sim:=get("test")!
|
||||
// //println(sim.sheet.rows.keys())
|
||||
// //println(spreadsheet.sheets_keys())
|
||||
// println(spreadsheet.sheet_get('bizmodel_test')!)
|
||||
// if true{panic("sss")}
|
||||
const action_priorities = {
|
||||
0: ['revenue_define', 'costcenter_define', 'funding_define']
|
||||
1: ['cost_define', 'department_define', 'employee_define']
|
||||
2: ['sheet_wiki', 'graph_bar_row', 'graph_pie_row', 'graph_line_row', 'row_overview']
|
||||
}
|
||||
|
||||
pub fn play(mut plbook PlayBook) ! {
|
||||
// group actions by which bizmodel they belong to
|
||||
actions_by_biz := arrays.group_by[string, &Action](
|
||||
plbook.actions_find(actor: 'bizmodel')!,
|
||||
fn (a &Action) string {
|
||||
return a.params.get('bizname') or {'default'}
|
||||
}
|
||||
)
|
||||
|
||||
// play actions for each biz in playbook
|
||||
for biz, actions in actions_by_biz {
|
||||
mut model := getset(biz)!
|
||||
model.play(mut plbook)!
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut m BizModel) play(mut plbook PlayBook) ! {
|
||||
mut actions := plbook.actions_find(actor: 'bizmodel')!
|
||||
|
||||
for action in actions.filter(it.name in action_priorities[0]) {
|
||||
m.act(*action)!
|
||||
}
|
||||
|
||||
m.cost_total()!
|
||||
m.revenue_total()!
|
||||
m.funding_total()!
|
||||
|
||||
for action in actions.filter(it.name in action_priorities[1]) {
|
||||
m.act(*action)!
|
||||
}
|
||||
|
||||
for action in actions.filter(it.name in action_priorities[2]) {
|
||||
m.act(*action)!
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ module bizmodel
|
||||
import freeflowuniverse.herolib.core.playbook { Action }
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
|
||||
fn (mut m BizModel) cost_define_action(action Action) ! {
|
||||
fn (mut m BizModel) cost_define_action(action Action) !Action {
|
||||
mut name := action.params.get_default('name', '')!
|
||||
mut descr := action.params.get_default('descr', '')!
|
||||
if descr.len == 0 {
|
||||
@@ -73,6 +73,7 @@ fn (mut m BizModel) cost_define_action(action Action) ! {
|
||||
)!
|
||||
m.sheet.row_delete('tmp3')
|
||||
}
|
||||
return action
|
||||
}
|
||||
|
||||
fn (mut sim BizModel) cost_total() ! {
|
||||
|
||||
@@ -3,7 +3,7 @@ module bizmodel
|
||||
import freeflowuniverse.herolib.core.playbook { Action }
|
||||
import freeflowuniverse.herolib.core.texttools
|
||||
|
||||
fn (mut m BizModel) costcenter_define_action(action Action) ! {
|
||||
fn (mut m BizModel) costcenter_define_action(action Action) !Action {
|
||||
mut name := action.params.get_default('name', '')!
|
||||
mut descr := action.params.get_default('descr', '')!
|
||||
if descr.len == 0 {
|
||||
@@ -20,4 +20,5 @@ fn (mut m BizModel) costcenter_define_action(action Action) ! {
|
||||
department: department
|
||||
}
|
||||
m.costcenters[name] = &cc
|
||||
return action
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import freeflowuniverse.herolib.core.texttools
|
||||
// - descr: description of the funding .
|
||||
// - investment is month:amount,month:amount, ... .
|
||||
// - type: loan or capital .
|
||||
fn (mut m BizModel) funding_define_action(action Action) ! {
|
||||
fn (mut m BizModel) funding_define_action(action Action) !Action {
|
||||
mut name := action.params.get_default('name', '')!
|
||||
mut descr := action.params.get_default('descr', '')!
|
||||
if descr.len == 0 {
|
||||
@@ -29,6 +29,7 @@ fn (mut m BizModel) funding_define_action(action Action) ! {
|
||||
descr: descr
|
||||
extrapolate: false
|
||||
)!
|
||||
return action
|
||||
}
|
||||
|
||||
fn (mut sim BizModel) funding_total() ! {
|
||||
|
||||
@@ -15,7 +15,7 @@ import freeflowuniverse.herolib.core.texttools
|
||||
// department:'engineering'
|
||||
// cost_percent_revenue e.g. 4%, will make sure the cost will be at least 4% of revenue
|
||||
|
||||
fn (mut m BizModel) employee_define_action(action Action) ! {
|
||||
fn (mut m BizModel) employee_define_action(action Action) !Action {
|
||||
mut name := action.params.get_default('name', '')!
|
||||
mut descr := action.params.get_default('descr', '')!
|
||||
if descr.len == 0 {
|
||||
@@ -107,10 +107,7 @@ fn (mut m BizModel) employee_define_action(action Action) ! {
|
||||
fulltime_perc: action.params.get_percentage_default('fulltime', '100%')!
|
||||
}
|
||||
|
||||
// println(employee)
|
||||
|
||||
// todo: use existing id gen
|
||||
|
||||
if name != '' {
|
||||
// sid = smartid.sid_new('')!
|
||||
// // TODO: this isn't necessary if sid_new works correctly
|
||||
@@ -120,9 +117,10 @@ fn (mut m BizModel) employee_define_action(action Action) ! {
|
||||
// }
|
||||
m.employees[name] = &employee
|
||||
}
|
||||
return action
|
||||
}
|
||||
|
||||
fn (mut m BizModel) department_define_action(action Action) ! {
|
||||
fn (mut m BizModel) department_define_action(action Action) !Action {
|
||||
mut name := action.params.get_default('name', '')!
|
||||
mut descr := action.params.get_default('descr', '')!
|
||||
if descr.len == 0 {
|
||||
@@ -141,6 +139,8 @@ fn (mut m BizModel) department_define_action(action Action) ! {
|
||||
if name != '' {
|
||||
m.departments[name] = &department
|
||||
}
|
||||
|
||||
return action
|
||||
}
|
||||
|
||||
// fn (mut sim BizModel) hr_total() ! {
|
||||
|
||||
@@ -13,15 +13,13 @@ import freeflowuniverse.herolib.core.texttools
|
||||
// - cogs_setup, cost of good for 1 item at setup
|
||||
// - cogs_setup_delay, how many months before setup cogs starts, after sales
|
||||
// - cogs_setup_perc: what is percentage of the cogs (can change over time) for setup e.g. 0:50%
|
||||
|
||||
// - cogs_monthly, cost of goods for the monthly per 1 item
|
||||
// - cogs_monthly_delay, how many months before monthly cogs starts, after sales
|
||||
// - cogs_monthly_perc: what is percentage of the cogs (can change over time) for monthly e.g. 0:5%,12:10%
|
||||
|
||||
// - nr_sold: how many do we sell per month (is in growth format e.g. 10:100,20:200)
|
||||
// - nr_sold: how many do we sell per month (is in growth format e.g. 10:100,20:200, default is 1)
|
||||
// - nr_months_recurring: how many months is recurring, if 0 then no recurring
|
||||
//
|
||||
fn (mut m BizModel) revenue_action(action Action) ! {
|
||||
fn (mut m BizModel) revenue_action(action Action) !Action {
|
||||
mut name := action.params.get_default('name', '')!
|
||||
mut descr := action.params.get_default('descr', '')!
|
||||
if descr.len == 0 {
|
||||
@@ -62,6 +60,10 @@ fn (mut m BizModel) revenue_action(action Action) ! {
|
||||
extrapolate: false
|
||||
)!
|
||||
|
||||
println(action)
|
||||
println(revenue)
|
||||
exit(0)
|
||||
|
||||
mut revenue_setup := m.sheet.row_new(
|
||||
name: '${name}_revenue_setup'
|
||||
growth: action.params.get_default('revenue_setup', '0:0')!
|
||||
@@ -139,11 +141,6 @@ fn (mut m BizModel) revenue_action(action Action) ! {
|
||||
aggregatetype: .avg
|
||||
)!
|
||||
|
||||
// if true{
|
||||
// println(cogs_setup_perc)
|
||||
// println(cogs_monthly_perc)
|
||||
// panic("sdsd")
|
||||
// }
|
||||
|
||||
mut nr_sold := m.sheet.row_new(
|
||||
name: '${name}_nr_sold'
|
||||
@@ -211,10 +208,6 @@ fn (mut m BizModel) revenue_action(action Action) ! {
|
||||
nrmonths: nr_months_recurring
|
||||
aggregatetype: .max
|
||||
)!
|
||||
// if true{
|
||||
// println(nr_sold_recurring)
|
||||
// panic('sd')
|
||||
// }
|
||||
}
|
||||
|
||||
// cogs as percentage of revenue
|
||||
@@ -229,16 +222,17 @@ fn (mut m BizModel) revenue_action(action Action) ! {
|
||||
name: '${name}_cogs_monthly_from_perc'
|
||||
)!
|
||||
|
||||
// if true{
|
||||
// println(revenue_setup_total)
|
||||
// println(cogs_setup_perc)
|
||||
// println(cogs_setup_from_perc)
|
||||
// println("montlhy")
|
||||
// println(revenue_monthly_total)
|
||||
// println(cogs_monthly_perc)
|
||||
// println(cogs_monthly_from_perc)
|
||||
// panic("sdsd")
|
||||
// }
|
||||
println(action)
|
||||
println(nr_sold)
|
||||
println(revenue)
|
||||
println(revenue_setup_total)
|
||||
println(revenue_monthly_total)
|
||||
println(cogs_setup_perc)
|
||||
println(cogs_setup_from_perc)
|
||||
println(cogs_monthly_perc)
|
||||
println(cogs_monthly_from_perc)
|
||||
exit(0)
|
||||
|
||||
|
||||
// mut cogs_from_perc:=cogs_perc.action(action:.multiply,rows:[revenue],name:"cogs_from_perc")!
|
||||
|
||||
@@ -312,6 +306,7 @@ fn (mut m BizModel) revenue_action(action Action) ! {
|
||||
// panic("sdsd")
|
||||
|
||||
// }
|
||||
return action
|
||||
}
|
||||
|
||||
// revenue_total calculates and aggregates the total revenue and cost of goods sold (COGS) for the business model
|
||||
|
||||
6
lib/biz/bizmodel/templates/department.md
Normal file
6
lib/biz/bizmodel/templates/department.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# @{department.name}
|
||||
|
||||
|
||||
`@{department.description}`
|
||||
|
||||
**Cost To The Company:**
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
`@{employee.cost}`
|
||||
|
||||
@{employee_cost_chart}
|
||||
|
||||
@if employee.cost_percent_revenue > 0.0
|
||||
|
||||
|
||||
27
lib/biz/bizmodel/templates/employee_old.md
Normal file
27
lib/biz/bizmodel/templates/employee_old.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# @{employee.name}
|
||||
|
||||
|
||||
`@{employee.description}`
|
||||
|
||||
> department: `@{employee.department}`
|
||||
|
||||
**Cost To The Company:**
|
||||
|
||||
`@{employee.cost}`
|
||||
|
||||
@if employee.cost_percent_revenue > 0.0
|
||||
|
||||
**Cost Percent Revenue:**
|
||||
|
||||
`@{employee.cost_percent_revenue}%`
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@if employee.nrpeople.len > 1
|
||||
|
||||
**Number of People in this group**
|
||||
|
||||
`@{employee.nrpeople}`
|
||||
|
||||
@end
|
||||
7
lib/biz/bizmodel/templates/human_resources.md
Normal file
7
lib/biz/bizmodel/templates/human_resources.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Human Resources
|
||||
|
||||
| Name | Title | Nr People |
|
||||
|------|-------|-------|
|
||||
@for employee in model.employees.values()
|
||||
| @{employee.name} | @{employee.title} | @{employee.nrpeople} |
|
||||
@end
|
||||
@@ -2,53 +2,48 @@
|
||||
|
||||
## FUNDING
|
||||
|
||||
!!bizmodel.sheet_wiki includefilter:'funding'
|
||||
@{bizmodel.sheet.wiki(includefilter:'funding')!}
|
||||
|
||||
## REVENUE vs COGS
|
||||
|
||||
!!bizmodel.sheet_wiki includefilter:rev
|
||||
@{bizmodel.sheet.wiki(includefilter:'rev')!}
|
||||
|
||||
#### Revenue Lines
|
||||
|
||||
!!bizmodel.sheet_wiki title:'Revenue Total' includefilter:'revtotal'
|
||||
@{bizmodel.sheet.wiki(title:'Revenue Total', includefilter:'revtotal')!}
|
||||
|
||||
#### COGS Lines
|
||||
|
||||
!!bizmodel.sheet_wiki title:'COGS' includefilter:'cogstotal'
|
||||
@{bizmodel.sheet.wiki(title:'COGS', includefilter:'cogstotal')!}
|
||||
|
||||
## HR
|
||||
!!bizmodel.sheet_wiki title:'HR Teams' includefilter:'hrnr'
|
||||
|
||||
!!bizmodel.sheet_wiki title:'HR Costs' includefilter:'hrcost'
|
||||
@{bizmodel.sheet.wiki(title:'HR Teams', includefilter:'hrnr')!}
|
||||
|
||||
@{bizmodel.sheet.wiki(title:'HR Costs', includefilter:'hrcost')!}
|
||||
|
||||
## Operational Costs
|
||||
|
||||
!!bizmodel.sheet_wiki title:'COSTS' includefilter:'ocost'
|
||||
|
||||
@{bizmodel.sheet.wiki(title:'COSTS', includefilter:'ocost')!}
|
||||
|
||||
## P&L Overview
|
||||
|
||||
<!-- period is in months, 3 means every quarter -->
|
||||
|
||||
!!bizmodel.sheet_wiki title:'P&L Overview' includefilter:'pl'
|
||||
@{bizmodel.sheet.wiki(title:'P&L Overview', includefilter:'pl')!}
|
||||
|
||||
|
||||
!!bizmodel.graph_bar_row rowname:revenue_total unit:million title:'A Title' title_sub:'Sub'
|
||||
@{bizmodel.graph_bar_row(rowname:'revenue_total', unit:'million', title:'A Title', title_sub:'Sub')!}
|
||||
|
||||
Unit is in Million USD.
|
||||
|
||||
!!bizmodel.graph_bar_row rowname:revenue_total unit:million
|
||||
@{bizmodel.graph_bar_row(rowname:'revenue_total', unit:'million')!}
|
||||
|
||||
!!bizmodel.graph_line_row rowname:revenue_total unit:million
|
||||
|
||||
!!bizmodel.graph_pie_row rowname:revenue_total unit:million size:'80%'
|
||||
@{bizmodel.graph_line_row(rowname:'revenue_total', unit:'million')!}
|
||||
|
||||
@{bizmodel.graph_pie_row(rowname:'revenue_total', unit:'million', size:'80%')!}
|
||||
|
||||
## Some Details
|
||||
|
||||
> show how we can do per month
|
||||
|
||||
!!bizmodel.sheet_wiki includefilter:'pl' period_months:1
|
||||
|
||||
|
||||
|
||||
@{bizmodel.sheet_wiki(includefilter:'pl', period_months:1)!}
|
||||
49
lib/biz/bizmodel/templates/introduction.md
Normal file
49
lib/biz/bizmodel/templates/introduction.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# @{model.name}
|
||||
|
||||
@{model.description}
|
||||
|
||||
## FUNDING
|
||||
|
||||
@{model.sheet.wiki(includefilter:['funding']) or {panic(err)}}
|
||||
|
||||
## REVENUE vs COGS
|
||||
|
||||
@{model.sheet.wiki(includefilter:['rev']) or {panic(err)}}
|
||||
|
||||
#### Revenue Lines
|
||||
|
||||
@{model.sheet.wiki(title:'Revenue Total', includefilter:['revtotal']) or {panic(err)}}
|
||||
|
||||
#### COGS Lines
|
||||
|
||||
@{model.sheet.wiki(title:'COGS', includefilter:['cogstotal']) or {panic(err)}}
|
||||
|
||||
## HR
|
||||
|
||||
@{model.sheet.wiki(title:'HR Teams', includefilter:['hrnr']) or {panic(err)}}
|
||||
|
||||
@{model.sheet.wiki(title:'HR Costs', includefilter:['hrcost']) or {panic(err)}}
|
||||
|
||||
## Operational Costs
|
||||
|
||||
@{model.sheet.wiki(title:'COSTS', includefilter:['ocost']) or {panic(err)}}
|
||||
|
||||
## P&L Overview
|
||||
|
||||
<!-- period is in months, 3 means every quarter -->
|
||||
|
||||
@{model.sheet.wiki(title:'P&L Overview', includefilter:['pl']) or {panic(err)}}
|
||||
|
||||
@{model.sheet.bar_chart(rowname:'revenue_total', unit: .million, title:'A Title', title_sub:'Sub') or {panic(err)}.mdx()}
|
||||
|
||||
Unit is in Million USD.
|
||||
|
||||
@{model.sheet.line_chart(rowname:'revenue_total', unit: .million) or {panic(err)}.mdx()}
|
||||
|
||||
@{model.sheet.pie_chart(rowname:'revenue_total', unit: .million, size:'80%') or {panic(err)}.mdx()}
|
||||
|
||||
## Some Details
|
||||
|
||||
> show how we can do per month
|
||||
|
||||
@{model.sheet.wiki(includefilter:['pl'], period_type:.month) or {panic(err)}}
|
||||
62
lib/biz/bizmodel/templates/product.md
Normal file
62
lib/biz/bizmodel/templates/product.md
Normal file
@@ -0,0 +1,62 @@
|
||||
|
||||
# @{product.title}
|
||||
|
||||
@{product.description}
|
||||
|
||||
#### parameters for the product
|
||||
|
||||
@if product.has_oneoffs
|
||||
|
||||
Product ${name1} has revenue events (one offs)
|
||||
|
||||
@{model.sheet.wiki() or {''}}
|
||||
namefilter:'${name1}_revenue,${name1}_cogs,${name1}_cogs_perc,${name1}_maintenance_month_perc' sheetname:'bizmodel_tf9
|
||||
|
||||
- COGS = Cost of Goods Sold (is our cost to deliver the product/service)
|
||||
- maintenance is fee we charge to the customer per month in relation to the revenue we charged e.g. 1% of a product which was sold for 1m EUR means we charge 1% of 1 m EUR per month.
|
||||
|
||||
@end //one offs
|
||||
|
||||
@if product.has_items
|
||||
|
||||
Product sold and its revenue/cost of goods
|
||||
|
||||
@{model.sheet.wiki() or {''}}
|
||||
namefilter:'${name1}_nr_sold,${name1}_revenue_setup,${name1}_revenue_monthly,${name1}_cogs_setup,${name1}_cogs_setup_perc,${name1}_cogs_monthly,${name1}_cogs_monthly_perc'
|
||||
sheetname:'bizmodel_tf9
|
||||
|
||||
- nr sold, is the nr sold per month of ${name1}
|
||||
- revenue setup is setup per item for ${name1}, this is the money we receive. Similar there is a revenue monthly.
|
||||
- cogs = Cost of Goods Sold (is our cost to deliver the product)
|
||||
- can we as a setup per item, or per month per item
|
||||
|
||||
@if product.nr_months_recurring>1
|
||||
|
||||
This product ${name1} is recurring, means customer pays per month ongoing, the period customer is paying for in months is: **${product.nr_months_recurring}**
|
||||
|
||||
@end //recurring
|
||||
|
||||
@end
|
||||
|
||||
#### the revenue/cogs calculated
|
||||
|
||||
@{model.sheet.wiki() or {''}}
|
||||
namefilter:'${name1}_nr_sold_recurring'
|
||||
sheetname:'bizmodel_tf9
|
||||
|
||||
This results in following revenues and cogs:
|
||||
|
||||
@{model.sheet.wiki() or {''}}
|
||||
namefilter:'${name1}_revenue_setup_total,${name1}_revenue_monthly_total,${name1}_cogs_setup_total,${name1}_cogs_monthly_total,${name1}_cogs_setup_from_perc,${name1}_cogs_monthly_from_perc,${name1}_maintenance_month,
|
||||
${name1}_revenue_monthly_recurring,${name1}_cogs_monthly_recurring'
|
||||
sheetname:'bizmodel_tf9
|
||||
|
||||
resulting revenues:
|
||||
@{model.sheet.wiki() or {''}}
|
||||
namefilter:'${name1}_revenue_total,${name1}_cogs_total'
|
||||
sheetname:'bizmodel_tf9
|
||||
|
||||
|
||||
!!!spreadsheet.graph_line_row rowname:'${name1}_cogs_total' unit:million sheetname:'bizmodel_tf9'
|
||||
|
||||
!!!spreadsheet.graph_line_row rowname:'${name1}_revenue_total' unit:million sheetname:'bizmodel_tf9'
|
||||
68
lib/biz/bizmodel/templates/product_old.md
Normal file
68
lib/biz/bizmodel/templates/product_old.md
Normal file
@@ -0,0 +1,68 @@
|
||||
|
||||
# @{product.title}
|
||||
|
||||
@{product.description}
|
||||
|
||||
#### parameters for the product
|
||||
|
||||
@if product.has_oneoffs
|
||||
|
||||
Product ${name1} has revenue events (one offs)
|
||||
|
||||
!!!spreadsheet.sheet_wiki
|
||||
namefilter:'${name1}_revenue,${name1}_cogs,${name1}_cogs_perc,${name1}_maintenance_month_perc' sheetname:'bizmodel_tf9
|
||||
|
||||
- COGS = Cost of Goods Sold (is our cost to deliver the product/service)
|
||||
- maintenance is fee we charge to the customer per month in relation to the revenue we charged e.g. 1% of a product which was sold for 1m EUR means we charge 1% of 1 m EUR per month.
|
||||
|
||||
@end //one offs
|
||||
|
||||
@if product.has_items
|
||||
|
||||
Product sold and its revenue/cost of goods
|
||||
|
||||
!!!spreadsheet.sheet_wiki
|
||||
namefilter:'${name1}_nr_sold,${name1}_revenue_setup,${name1}_revenue_monthly,${name1}_cogs_setup,${name1}_cogs_setup_perc,${name1}_cogs_monthly,${name1}_cogs_monthly_perc'
|
||||
sheetname:'bizmodel_tf9
|
||||
|
||||
- nr sold, is the nr sold per month of ${name1}
|
||||
- revenue setup is setup per item for ${name1}, this is the money we receive. Similar there is a revenue monthly.
|
||||
- cogs = Cost of Goods Sold (is our cost to deliver the product)
|
||||
- can we as a setup per item, or per month per item
|
||||
|
||||
@if product.nr_months_recurring>1
|
||||
|
||||
This product ${name1} is recurring, means customer pays per month ongoing, the period customer is paying for in months is: **${product.nr_months_recurring}**
|
||||
|
||||
@end //recurring
|
||||
|
||||
@end
|
||||
|
||||
#### the revenue/cogs calculated
|
||||
|
||||
|
||||
!!!spreadsheet.sheet_wiki
|
||||
namefilter:'${name1}_nr_sold_recurring'
|
||||
sheetname:'bizmodel_tf9
|
||||
|
||||
This results in following revenues and cogs:
|
||||
|
||||
!!!spreadsheet.sheet_wiki
|
||||
namefilter:'${name1}_revenue_setup_total,${name1}_revenue_monthly_total,${name1}_cogs_setup_total,${name1}_cogs_monthly_total,${name1}_cogs_setup_from_perc,${name1}_cogs_monthly_from_perc,${name1}_maintenance_month,
|
||||
${name1}_revenue_monthly_recurring,${name1}_cogs_monthly_recurring'
|
||||
sheetname:'bizmodel_tf9
|
||||
|
||||
resulting revenues:
|
||||
!!!spreadsheet.sheet_wiki
|
||||
namefilter:'${name1}_revenue_total,${name1}_cogs_total'
|
||||
sheetname:'bizmodel_tf9
|
||||
|
||||
|
||||
!!!spreadsheet.graph_line_row rowname:'${name1}_cogs_total' unit:million sheetname:'bizmodel_tf9'
|
||||
|
||||
!!!spreadsheet.graph_line_row rowname:'${name1}_revenue_total' unit:million sheetname:'bizmodel_tf9'
|
||||
|
||||
|
||||
@end //product has_revenue
|
||||
|
||||
@end //loop
|
||||
@@ -124,9 +124,4 @@ fn test_curr() {
|
||||
console.print_debug(sh.rows['something'].cells[0])
|
||||
assert sh.rows['something']!.cells[0].val == 25.0
|
||||
assert sh.rows['something']!.cells[60 - 1].val == 900.0
|
||||
|
||||
// TODO: we need to create tests for it
|
||||
|
||||
console.print_debug(sh)
|
||||
panic('test1')
|
||||
}
|
||||
|
||||
138
lib/biz/spreadsheet/charts.v
Normal file
138
lib/biz/spreadsheet/charts.v
Normal file
@@ -0,0 +1,138 @@
|
||||
module spreadsheet
|
||||
|
||||
import freeflowuniverse.herolib.data.markdownparser.elements
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.web.echarts
|
||||
|
||||
pub fn (s Sheet) title_chart(args RowGetArgs) echarts.EChartsOption {
|
||||
return echarts.EChartsOption{
|
||||
title: echarts.Title{
|
||||
text: args.title
|
||||
subtext: args.title_sub
|
||||
left: 'center'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (s Sheet) line_chart(args_ RowGetArgs) !echarts.EChartsOption {
|
||||
mut args := args_
|
||||
|
||||
rownames := s.rownames_get(args)!
|
||||
header := s.header_get_as_string(args.period_type)!
|
||||
mut series := []echarts.Series{}
|
||||
|
||||
for rowname in rownames {
|
||||
data := s.data_get_as_string(RowGetArgs{
|
||||
...args
|
||||
rowname: rowname
|
||||
})!
|
||||
series << echarts.Series{
|
||||
name: rowname
|
||||
type_: 'line'
|
||||
stack: 'Total'
|
||||
data: data.split(',')
|
||||
}
|
||||
}
|
||||
|
||||
return echarts.EChartsOption{
|
||||
title: s.title_chart(args).title
|
||||
tooltip: echarts.Tooltip{
|
||||
trigger: 'axis'
|
||||
}
|
||||
legend: echarts.Legend{
|
||||
data: rownames
|
||||
}
|
||||
grid: echarts.Grid{
|
||||
left: '3%'
|
||||
right: '4%'
|
||||
bottom: '3%'
|
||||
contain_label: true
|
||||
}
|
||||
toolbox: echarts.Toolbox{
|
||||
feature: echarts.ToolboxFeature{
|
||||
save_as_image: {}
|
||||
}
|
||||
}
|
||||
x_axis: echarts.XAxis{
|
||||
type_: 'category'
|
||||
boundary_gap: false
|
||||
data: header.split(',')
|
||||
}
|
||||
y_axis: echarts.YAxis{
|
||||
type_: 'value'
|
||||
}
|
||||
series: series
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (s Sheet) bar_chart(args_ RowGetArgs) !echarts.EChartsOption {
|
||||
mut args := args_
|
||||
args.rowname = s.rowname_get(args)!
|
||||
header := s.header_get_as_list(args.period_type)!
|
||||
data := s.data_get_as_list(args)!
|
||||
|
||||
return echarts.EChartsOption{
|
||||
title: s.title_chart(args).title
|
||||
x_axis: echarts.XAxis{
|
||||
type_: 'category'
|
||||
data: header
|
||||
}
|
||||
y_axis: echarts.YAxis{
|
||||
type_: 'value'
|
||||
}
|
||||
series: [
|
||||
echarts.Series{
|
||||
name: args.rowname
|
||||
type_: 'bar'
|
||||
data: data
|
||||
stack: ''
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (s Sheet) pie_chart(args_ RowGetArgs) !echarts.EChartsOption {
|
||||
mut args := args_
|
||||
args.rowname = s.rowname_get(args)!
|
||||
header := s.header_get_as_list(args.period_type)!
|
||||
data := s.data_get_as_list(args)!
|
||||
|
||||
if header.len != data.len {
|
||||
return error('Data and header lengths must match.')
|
||||
}
|
||||
|
||||
mut pie_data := []map[string]string{}
|
||||
for i, _ in data {
|
||||
pie_data << {
|
||||
'value': data[i].trim_space().trim("'")
|
||||
'name': header[i].trim_space().trim("'")
|
||||
}
|
||||
}
|
||||
|
||||
return echarts.EChartsOption{
|
||||
title: s.title_chart(args).title
|
||||
tooltip: echarts.Tooltip{
|
||||
trigger: 'item'
|
||||
}
|
||||
legend: echarts.Legend{
|
||||
data: header
|
||||
orient: 'vertical'
|
||||
left: 'left'
|
||||
}
|
||||
series: [
|
||||
echarts.Series{
|
||||
name: 'Data'
|
||||
type_: 'pie'
|
||||
radius: args.size.int()
|
||||
data: pie_data.map(it.str())
|
||||
emphasis: echarts.Emphasis{
|
||||
item_style: echarts.ItemStyle{
|
||||
shadow_blur: 10
|
||||
shadow_offset_x: 0
|
||||
shadow_color: 'rgba(0, 0, 0, 0.5)'
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
77
lib/biz/spreadsheet/charts_test.v
Normal file
77
lib/biz/spreadsheet/charts_test.v
Normal file
@@ -0,0 +1,77 @@
|
||||
module spreadsheet
|
||||
|
||||
import freeflowuniverse.herolib.data.markdownparser.elements
|
||||
import freeflowuniverse.herolib.ui.console
|
||||
import freeflowuniverse.herolib.web.echarts
|
||||
|
||||
fn test_title_chart() {
|
||||
mut s := sheet_new() or { panic(err) }
|
||||
mut nrnodes := s.row_new(
|
||||
name: 'nrnodes'
|
||||
growth: '5:100,55:1000'
|
||||
tags: 'cat:nodes color:yellow urgent'
|
||||
)!
|
||||
args := RowGetArgs{
|
||||
rowname: 'nrnodes'
|
||||
title: 'Main Title'
|
||||
title_sub: 'Subtitle'
|
||||
}
|
||||
title := s.title_chart(args).title
|
||||
assert title.text == 'Main Title'
|
||||
assert title.subtext == 'Subtitle'
|
||||
assert title.left == 'center'
|
||||
}
|
||||
|
||||
fn test_line_chart() {
|
||||
mut s := sheet_new() or { panic(err) }
|
||||
mut nrnodes := s.row_new(
|
||||
name: 'nrnodes'
|
||||
growth: '5:100,55:1000'
|
||||
tags: 'cat:nodes color:yellow urgent'
|
||||
)!
|
||||
args := RowGetArgs{
|
||||
rowname: 'nrnodes'
|
||||
title: 'Line Chart'
|
||||
period_type: .month
|
||||
}
|
||||
option := s.line_chart(args) or { panic(err) }
|
||||
assert option.title.text == 'Line Chart'
|
||||
assert option.tooltip.trigger == 'axis'
|
||||
assert option.grid.contain_label == true
|
||||
}
|
||||
|
||||
fn test_bar_chart() {
|
||||
mut s := sheet_new() or { panic(err) }
|
||||
mut nrnodes := s.row_new(
|
||||
name: 'nrnodes'
|
||||
growth: '5:100,55:1000'
|
||||
tags: 'cat:nodes color:yellow urgent'
|
||||
)!
|
||||
args := RowGetArgs{
|
||||
rowname: 'nrnodes'
|
||||
title: 'Bar Chart'
|
||||
period_type: .year
|
||||
}
|
||||
option := s.bar_chart(args) or { panic(err) }
|
||||
assert option.title.text == 'Bar Chart'
|
||||
assert option.x_axis.type_ == 'category'
|
||||
assert option.y_axis.type_ == 'value'
|
||||
}
|
||||
|
||||
fn test_pie_chart() {
|
||||
mut s := sheet_new() or { panic(err) }
|
||||
mut nrnodes := s.row_new(
|
||||
name: 'nrnodes'
|
||||
growth: '5:100,55:1000'
|
||||
tags: 'cat:nodes color:yellow urgent'
|
||||
)!
|
||||
args := RowGetArgs{
|
||||
rowname: 'nrnodes'
|
||||
title: 'Pie Chart'
|
||||
period_type: .quarter
|
||||
}
|
||||
option := s.pie_chart(args) or { panic(err) }
|
||||
assert option.title.text == 'Pie Chart'
|
||||
assert option.tooltip.trigger == 'item'
|
||||
assert option.legend.data.len > 0
|
||||
}
|
||||
@@ -92,7 +92,7 @@ pub fn playmacro(action Action) !string {
|
||||
content = sh.wiki(args) or { panic(err) }
|
||||
}
|
||||
'graph_title_row' {
|
||||
content = sh.wiki_title_chart(args)
|
||||
content = sh.wiki_title_chart(args)!
|
||||
}
|
||||
'graph_line_row' {
|
||||
content = sh.wiki_line_chart(args)!
|
||||
|
||||
@@ -95,7 +95,7 @@ pub fn (mut r Row) cell_get(colnr int) !&Cell {
|
||||
return &r.cells[colnr]
|
||||
}
|
||||
|
||||
pub fn (mut r Row) values_get() []f64 {
|
||||
pub fn (r Row) values_get() []f64 {
|
||||
mut out := []f64{}
|
||||
for cell in r.cells {
|
||||
out << cell.val
|
||||
|
||||
@@ -202,7 +202,7 @@ pub fn (s Sheet) tosmaller(args_ ToYearQuarterArgs) !&Sheet {
|
||||
// tagsfilter []string
|
||||
// tags if set will see that there is at least one corresponding tag per row
|
||||
// rawsfilter is list of names of rows which will be included
|
||||
pub fn (mut s Sheet) toyear(args ToYearQuarterArgs) !&Sheet {
|
||||
pub fn (s Sheet) toyear(args ToYearQuarterArgs) !&Sheet {
|
||||
mut args2 := args
|
||||
args2.period_months = 12
|
||||
return s.tosmaller(args2)
|
||||
@@ -215,7 +215,7 @@ pub fn (mut s Sheet) toyear(args ToYearQuarterArgs) !&Sheet {
|
||||
// tagsfilter []string
|
||||
// tags if set will see that there is at least one corresponding tag per row
|
||||
// rawsfilter is list of names of rows which will be included
|
||||
pub fn (mut s Sheet) toquarter(args ToYearQuarterArgs) !&Sheet {
|
||||
pub fn (s Sheet) toquarter(args ToYearQuarterArgs) !&Sheet {
|
||||
mut args2 := args
|
||||
args2.period_months = 3
|
||||
return s.tosmaller(args2)
|
||||
@@ -259,13 +259,15 @@ pub fn (mut s Sheet) json() string {
|
||||
}
|
||||
|
||||
// find row, report error if not found
|
||||
pub fn (mut s Sheet) row_get(name string) !&Row {
|
||||
mut row := s.rows[name] or { return error('could not find row with name: ${name}') }
|
||||
pub fn (s Sheet) row_get(name string) !&Row {
|
||||
row := s.rows[name] or {
|
||||
return error('could not find row with name: ${name}, available rows: ${s.rows.keys()}')
|
||||
}
|
||||
return row
|
||||
}
|
||||
|
||||
pub fn (mut s Sheet) values_get(name string) ![]f64 {
|
||||
mut r := s.row_get(name)!
|
||||
pub fn (s Sheet) values_get(name string) ![]f64 {
|
||||
r := s.row_get(name)!
|
||||
vs := r.values_get()
|
||||
return vs
|
||||
}
|
||||
|
||||
49
lib/biz/spreadsheet/sheet_export.v
Normal file
49
lib/biz/spreadsheet/sheet_export.v
Normal file
@@ -0,0 +1,49 @@
|
||||
module spreadsheet
|
||||
import os
|
||||
import freeflowuniverse.herolib.core.pathlib
|
||||
|
||||
@[params]
|
||||
pub struct ExportArgs{
|
||||
pub mut:
|
||||
path string
|
||||
}
|
||||
|
||||
fn format_number(val f64) string {
|
||||
if val < 0.001 && val > -0.001 {
|
||||
return '0'
|
||||
}
|
||||
if val >= 1000.0 || val <= -1000.0 {
|
||||
return int(val).str()
|
||||
}
|
||||
// Format small numbers with 3 decimal places to handle floating point precision
|
||||
return '${val:.3f}'
|
||||
}
|
||||
|
||||
pub fn (mut s Sheet) export(args ExportArgs) !string {
|
||||
mut result := []string{}
|
||||
|
||||
// Add headers
|
||||
mut header_row := ['Name', 'Description', 'AggregateType', 'Tags', 'Subgroup']
|
||||
header_row << s.header()!
|
||||
result << header_row.join('|')
|
||||
|
||||
// Add rows
|
||||
for _, row in s.rows {
|
||||
mut row_data := [row.name, row.description, row.aggregatetype.str(), row.tags, row.subgroup]
|
||||
for cell in row.cells {
|
||||
if cell.empty {
|
||||
row_data << '-'
|
||||
} else {
|
||||
row_data << format_number(cell.val)
|
||||
}
|
||||
}
|
||||
result << row_data.join('|')
|
||||
}
|
||||
|
||||
if args.path.len>0{
|
||||
mut p:=pathlib.get_file(path:args.path.replace("~",os.home_dir()), create:true, delete:true)!
|
||||
p.write(result.join('\n'))!
|
||||
}
|
||||
|
||||
return result.join('\n')
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user