Flesh out runtime
This commit is contained in:
parent
61fede23ab
commit
ce41860c5c
8 changed files with 152 additions and 45 deletions
6
go.mod
6
go.mod
|
@ -2,11 +2,13 @@ module github.com/codemicro/adventOfCode
|
|||
|
||||
go 1.17
|
||||
|
||||
require github.com/AlecAivazis/survey/v2 v2.3.2
|
||||
|
||||
require (
|
||||
github.com/AlecAivazis/survey/v2 v2.3.2 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
|
||||
github.com/mattn/go-colorable v0.1.2 // indirect
|
||||
github.com/mattn/go-isatty v0.0.8 // indirect
|
||||
github.com/mattn/go-isatty v0.0.13 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect
|
||||
golang.org/x/term v0.0.0-20210503060354-a79de5458b56 // indirect
|
||||
|
|
12
go.sum
12
go.sum
|
@ -1,18 +1,27 @@
|
|||
github.com/AlecAivazis/survey/v2 v2.3.2 h1:TqTB+aDDCLYhf9/bD2TwSO8u8jDSmMUd2SUVO4gCnU8=
|
||||
github.com/AlecAivazis/survey/v2 v2.3.2/go.mod h1:TH2kPCDU3Kqq7pLbnCWwZXDBjnhZtmsCle5EiYDJ2fg=
|
||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
|
||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ=
|
||||
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kr/pty v1.1.4 h1:5Myjjh3JY/NaAi4IsUbHADytDyl1VE1Y9PXDlL+P/VQ=
|
||||
github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
|
||||
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U=
|
||||
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
|
@ -20,6 +29,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20210503060354-a79de5458b56 h1:b8jxX3zqjpqb2LklXPzKSGJhzyxCOZSz8ncv8Nv+y7w=
|
||||
|
|
|
@ -5,32 +5,31 @@ import (
|
|||
"io/ioutil"
|
||||
)
|
||||
|
||||
type ChallengeInfo struct {
|
||||
type Info struct {
|
||||
InputFile string `json:"inputFile"`
|
||||
TestCases struct {
|
||||
One []struct {
|
||||
Input string `json:"input"`
|
||||
Expected int64 `json:"expected"`
|
||||
} `json:"one"`
|
||||
Two []struct {
|
||||
Input string `json:"input"`
|
||||
Expected int `json:"expected"`
|
||||
} `json:"two"`
|
||||
One []*TestCase `json:"one"`
|
||||
Two []*TestCase `json:"two"`
|
||||
} `json:"testCases"`
|
||||
}
|
||||
|
||||
func LoadChallengeInfo(fname string) (*ChallengeInfo, error) {
|
||||
type TestCase struct {
|
||||
Input string `json:"input"`
|
||||
Expected interface{} `json:"expected"`
|
||||
}
|
||||
|
||||
func LoadChallengeInfo(fname string) (*Info, error) {
|
||||
|
||||
fcont, err := ioutil.ReadFile(fname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := new(ChallengeInfo)
|
||||
c := new(Info)
|
||||
err = json.Unmarshal(fcont, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,16 +96,19 @@ func run() error {
|
|||
challengeInputString := string(challengeInput)
|
||||
|
||||
runner := runners.Available[selectedImplementation](selectedChallenge.Dir)
|
||||
runner.Queue(&runners.Task{
|
||||
Part: 1,
|
||||
Input: challengeInputString,
|
||||
})
|
||||
|
||||
lookupTable := make(taskLookupTable)
|
||||
setupTestTasks(challengeInfo, runner, &lookupTable)
|
||||
setupMainTasks(challengeInputString, runner, &lookupTable)
|
||||
|
||||
fmt.Println("\nRunning...\n")
|
||||
|
||||
for roe := range runner.Run() {
|
||||
if roe.Error != nil {
|
||||
return roe.Error
|
||||
}
|
||||
fmt.Println(*roe.Result)
|
||||
// fmt.Println(*roe.Result)
|
||||
lookupTable[roe.Result.TaskID](roe.Result)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -11,13 +11,14 @@ import (
|
|||
)
|
||||
|
||||
type Task struct {
|
||||
TaskID string `json:"task_id"`
|
||||
Part Part `json:"part"`
|
||||
Input string `json:"input"`
|
||||
OutputDir string `json:"output_dir,omitempty"`
|
||||
}
|
||||
|
||||
type Result struct {
|
||||
TaskNumber int `json:"task_n"`
|
||||
TaskID string `json:"task_id"`
|
||||
Ok bool `json:"ok"`
|
||||
Output string `json:"output"`
|
||||
Duration float32 `json:"duration"`
|
||||
|
@ -30,8 +31,6 @@ func makeErrorChan(err error) chan ResultOrError {
|
|||
return c
|
||||
}
|
||||
|
||||
// custom writer type
|
||||
|
||||
type customWriter struct {
|
||||
pending []byte
|
||||
entries [][]byte
|
||||
|
|
|
@ -3,19 +3,20 @@ from py import Challenge
|
|||
import time
|
||||
import json
|
||||
|
||||
TASKS_STR = """{{ .TasksJSON }}"""
|
||||
TASKS_STR = input()
|
||||
TASKS = json.loads(TASKS_STR)
|
||||
|
||||
def send_result(task_number, ok, output, duration):
|
||||
def send_result(task_id, ok, output, duration):
|
||||
print(json.dumps({
|
||||
"task_n": task_number,
|
||||
"task_id": task_id,
|
||||
"ok": ok,
|
||||
"output": str(output) if output is not None else "",
|
||||
"duration": float(duration),
|
||||
}), flush=True)
|
||||
|
||||
for task_number, task in enumerate(TASKS):
|
||||
for task in TASKS:
|
||||
taskPart = task["part"]
|
||||
task_id = task["task_id"]
|
||||
|
||||
run = None
|
||||
|
||||
|
@ -26,7 +27,7 @@ for task_number, task in enumerate(TASKS):
|
|||
elif taskPart == 3:
|
||||
run = lambda: Challenge().vis(task["input"], task["output_dir"])
|
||||
else:
|
||||
send_result(task_number, False, "unknown task part", 0)
|
||||
send_result(task_id, False, "unknown task part", 0)
|
||||
continue
|
||||
|
||||
start_time = time.time()
|
||||
|
@ -41,6 +42,6 @@ for task_number, task in enumerate(TASKS):
|
|||
running_time = end_time-start_time
|
||||
|
||||
if err is not None:
|
||||
send_result(task_number, False, err, running_time)
|
||||
send_result(task_id, False, err, running_time)
|
||||
else:
|
||||
send_result(task_number, True, res, running_time)
|
||||
send_result(task_id, True, res, running_time)
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
const python3Installation = "python3"
|
||||
|
@ -29,32 +28,21 @@ func (p *pythonRunner) Queue(task *Task) {
|
|||
}
|
||||
|
||||
//go:embed interface/python.py
|
||||
var pythonInterface string
|
||||
var pythonInterface []byte
|
||||
|
||||
func (p *pythonRunner) Run() chan ResultOrError {
|
||||
|
||||
wrapperFilename := "runtime-wrapper.py"
|
||||
wrapperFilepath := filepath.Join(p.dir, wrapperFilename)
|
||||
|
||||
// Generate interaction code
|
||||
// Generate interaction data
|
||||
taskJSON, err := json.Marshal(p.tasks)
|
||||
if err != nil {
|
||||
return makeErrorChan(err)
|
||||
}
|
||||
|
||||
interactionCodeBuffer := new(bytes.Buffer)
|
||||
{
|
||||
templ := template.Must(template.New("").Parse(pythonInterface))
|
||||
err := templ.Execute(interactionCodeBuffer, struct{
|
||||
TasksJSON string
|
||||
}{string(taskJSON)})
|
||||
if err != nil {
|
||||
return makeErrorChan(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Save interaction code
|
||||
err = ioutil.WriteFile(wrapperFilepath, interactionCodeBuffer.Bytes(), 0644)
|
||||
err = ioutil.WriteFile(wrapperFilepath, pythonInterface, 0644)
|
||||
if err != nil {
|
||||
return makeErrorChan(err)
|
||||
}
|
||||
|
@ -63,6 +51,8 @@ func (p *pythonRunner) Run() chan ResultOrError {
|
|||
cmd := exec.Command(python3Installation, "-B", wrapperFilename) // -B prevents .pyc files from being written
|
||||
cmd.Dir = p.dir
|
||||
|
||||
cmd.Stdin = bytes.NewReader(append(taskJSON, '\n'))
|
||||
|
||||
return readResultsFromCommand(cmd, func() {
|
||||
// Remove leftover files
|
||||
_ = os.Remove(wrapperFilepath)
|
||||
|
|
103
runtime/tasks.go
Normal file
103
runtime/tasks.go
Normal file
|
@ -0,0 +1,103 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/codemicro/adventOfCode/runtime/challenge"
|
||||
"github.com/codemicro/adventOfCode/runtime/runners"
|
||||
au "github.com/logrusorgru/aurora"
|
||||
)
|
||||
|
||||
type taskLookupTable map[string]func(*runners.Result)
|
||||
|
||||
var (
|
||||
passLabel = au.BrightGreen("pass").String()
|
||||
failLabel = au.BrightRed("fail").String()
|
||||
incompleteLabel = au.BgBrightRed("did not complete").String()
|
||||
)
|
||||
|
||||
func setupTestTasks(info *challenge.Info, runner runners.Runner, table *taskLookupTable) {
|
||||
|
||||
st := func(part runners.Part, testCases []*challenge.TestCase, runner runners.Runner, table *taskLookupTable) {
|
||||
for i, testCase := range testCases {
|
||||
|
||||
// loop variables change, remember? :P
|
||||
i := i
|
||||
testCase := testCase
|
||||
|
||||
id := fmt.Sprintf("test.%d.%d", part, i)
|
||||
runner.Queue(&runners.Task{
|
||||
TaskID: id,
|
||||
Part: part,
|
||||
Input: testCase.Input,
|
||||
})
|
||||
|
||||
(*table)[id] = func(r *runners.Result) {
|
||||
|
||||
expected := fmt.Sprintf("%v", testCase.Expected)
|
||||
|
||||
passed := r.Output == expected
|
||||
|
||||
fmt.Print(au.Bold(fmt.Sprintf("Test %s: ",
|
||||
au.BrightBlue(fmt.Sprintf("%d.%d", part, i)),
|
||||
)))
|
||||
|
||||
var status string
|
||||
var followUpText string
|
||||
if !r.Ok {
|
||||
status = incompleteLabel
|
||||
followUpText = "saying \"" + r.Output + "\""
|
||||
} else if passed {
|
||||
status = passLabel
|
||||
} else {
|
||||
status = failLabel
|
||||
}
|
||||
|
||||
if followUpText == "" {
|
||||
followUpText = fmt.Sprintf("in %.4f seconds", r.Duration)
|
||||
}
|
||||
|
||||
fmt.Print(status)
|
||||
fmt.Println(au.Gray(10, " " + followUpText))
|
||||
|
||||
if !passed && r.Ok {
|
||||
fmt.Printf(" └ Expected %s, got %s\n", au.BrightBlue(expected), au.BrightBlue(r.Output))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
st(runners.PartOne, info.TestCases.One, runner, table)
|
||||
st(runners.PartTwo, info.TestCases.Two, runner, table)
|
||||
}
|
||||
|
||||
func setupMainTasks(input string, runner runners.Runner, table *taskLookupTable) {
|
||||
|
||||
for part := runners.PartOne; part <= runners.PartTwo; part += 1 {
|
||||
|
||||
part := part // loop variables need to be copied be used elsewhere to be used in function below, otherwise they
|
||||
// become rather wrong
|
||||
|
||||
id := fmt.Sprintf("main.%d", part)
|
||||
runner.Queue(&runners.Task{
|
||||
TaskID: id,
|
||||
Part: part,
|
||||
Input: input,
|
||||
})
|
||||
|
||||
(*table)[id] = func(r *runners.Result) {
|
||||
|
||||
fmt.Print(au.Bold(fmt.Sprintf("Part %d: ", au.Yellow(part))))
|
||||
|
||||
if !r.Ok {
|
||||
fmt.Print(incompleteLabel)
|
||||
fmt.Println(au.Gray(10, " saying \"" + r.Output + "\""))
|
||||
} else {
|
||||
fmt.Print(au.BrightBlue(r.Output))
|
||||
fmt.Println(au.Gray(10, fmt.Sprintf(" in %.4f seconds", r.Duration)))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue