Skip to content

Commit

Permalink
Near completion of activity logic
Browse files Browse the repository at this point in the history
  • Loading branch information
insyri committed Dec 31, 2023
1 parent 3980796 commit 1fc7c25
Show file tree
Hide file tree
Showing 14 changed files with 163 additions and 74 deletions.
7 changes: 0 additions & 7 deletions .idea/misc.xml

This file was deleted.

28 changes: 21 additions & 7 deletions cmd/lesson.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,37 @@ var lessonCmd = &cobra.Command{
Use: "lesson",
Short: "Starts the activity / Lists available activities",
Aliases: []string{"lessons", "list", "start"},
//Args: func(cmd *cobra.Command, args []string) error {
// if err := cobra.RangeArgs(0, 2)(cmd, args); err != nil {
// return err
// }
// // Run the custom validation logic
// if myapp.IsValidColor(args[0]) {
// return nil
// }
// return fmt.Errorf("invalid color specified: %s", args[0])
//},
// TODO: impl arg validator + pre-run (if l/c exists)
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
b := color.New(color.Bold)
for i := range lesson.Master.Lessons {
for i := 1; i < len(lesson.Master.Lessons); i++ {
L := lesson.Master.Lessons[i]
fmt.Printf("%-2d %s\n %s\n Author: %s\n\n", L.Id, b.Sprint(L.Name), L.Description, L.Author)
fmt.Printf("%-2d %s\n %s\n Author: %s"+
"\n\n",
i, color.New(color.Bold).Sprint(L.Name), L.Description, L.Author)
}
fmt.Println("Use \"csa start [number]\" to start the lesson that corresponds to the number.")
} else {
n, err := strconv.Atoi(args[0])
if err != nil {
util.LogErrorAndExit(err)
}
for i := range lesson.Master.Lessons {
if lesson.Master.Lessons[i].Id == uint8(n) {
fmt.Println(lesson.Master.Lessons[i].Name)
}
if n > len(lesson.Master.Lessons) || n == 0 {
util.LogErrorAndExit(util.NonexistentLesson)
}
err = lesson.Master.Run(n, 0)
if err != nil {
util.LogErrorAndExit(err)
}
}
},
Expand Down
6 changes: 3 additions & 3 deletions cmd/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@ import (
)

func init() {
readCmd.Hidden = true
rootCmd.AddCommand(readCmd)
}

var readCmd = &cobra.Command{
Use: "read",
Short: "Clears the lesson checkpoint",
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
info, err := util.Load()
if err != nil {
util.LogErrorAndExit(err)
return err
}

fmt.Printf(
"Timestamp: %d\n"+
"LessonID: %d\n"+
"CheckptID: %d\n", info.Time, info.LessonId, info.CheckpointID)
return nil
},
}
3 changes: 0 additions & 3 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package cmd
import (
"csclub-activities/util"
"github.com/spf13/cobra"
"os"
)

var rootCmd = &cobra.Command{
Expand All @@ -20,7 +19,5 @@ func Execute() {
// https://github.com/fatih/color?tab=readme-ov-file#disableenable-colorx

util.LogErrorAndExit(err)

os.Exit(1)
}
}
5 changes: 3 additions & 2 deletions cmd/stop.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ var stopCmd = &cobra.Command{
Use: "stop",
Short: "Clears the lesson checkpoint",
Aliases: []string{"clear", "new"},
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
err := util.NewSave()
if err != nil {
util.LogErrorAndExit(err)
return err
}
fmt.Println("Checkpoint cleared")
return nil
},
}
10 changes: 7 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ module csclub-activities
go 1.21.5

require (
github.com/fatih/color v1.16.0 // indirect
github.com/fatih/color v1.16.0
github.com/spf13/cobra v1.8.0
)

require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/spf13/cobra v1.8.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/sys v0.14.0 // indirect
golang.org/x/sys v0.15.0 // indirect
)
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
Expand All @@ -17,5 +19,7 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
56 changes: 43 additions & 13 deletions lesson/lesson.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package lesson

import "errors"
import (
"csclub-activities/util"
"fmt"
"github.com/fatih/color"
)

/*
save checkpoint
Expand All @@ -13,34 +17,60 @@ metadata:
*/

func init() {
// Empty first struct to support the NoOngoingActivity functionality
l := []*Lesson{{}, lessonOne, lessonTwo}
for x := range l {
Master.Lessons = append(Master.Lessons, *l[x])
}
}

var Master master

type master struct {
Lessons []Lesson
}

func (m *master) append(newLesson *Lesson) error {
for i := range m.Lessons {
if m.Lessons[i].Id == newLesson.Id {
// here for future contributors
return errors.New("duplicate lesson ids")
}
func (m *master) Run(lesson int, checkpoint int) error {

if m.Lessons == nil ||
lesson >= len(m.Lessons) {
return util.NonexistentLesson
}

if m.Lessons[lesson].Checkpoints == nil ||
checkpoint >= len(m.Lessons[lesson].Checkpoints) {
return util.NonexistentCheckpoint
}

for i := checkpoint; i < len(m.Lessons[lesson].Checkpoints); i++ {

cp := m.Lessons[lesson].Checkpoints[i]
fmt.Printf("%-5s %s\n\n",
color.New(color.Bold).Add(color.FgGreen).Sprintf("%-2d/%-2d", i, len(m.Lessons)),
color.New(color.Bold).Sprintf("%s", cp.Title),
)
cp.Action(uint8(lesson), uint8(checkpoint))
}
m.Lessons = append(m.Lessons, *newLesson)
return nil
}

type Lesson struct {
Id uint8
Author string
Name string
Description string
Checkpoints []Checkpoint
}

type Checkpoint struct {
PreCondition func() bool // precondition could be previous checkpoint condition
Condition func() bool
Action func()
Position uint8
Title string
Action func(lessonID uint8, checkpointID uint8)
// What is the condition that allows the user to go onto the next checkpoint?
ShouldPromote func() bool
ExpectedErrors []ExpectantError
}

type ExpectantError struct {
MatchesError func() bool
Feedback string
}
60 changes: 52 additions & 8 deletions lesson/one.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,60 @@
package lesson

func init() {
err := Master.append(lessonOne)
if err != nil {
panic(err)
}
}
import (
"csclub-activities/util"
"fmt"
"github.com/mitchellh/go-wordwrap"
"os"
"runtime"
)

var lessonOne = &Lesson{
Id: 1,
Author: "Noah Mercedes",
Name: "Introduction to the Terminal + Getting Started",
Description: "Learn the basics of using the terminal! (todo desc)",
Checkpoints: nil,
Checkpoints: []Checkpoint{
{
Title: "Getting Started",
Action: func(lessonID uint8, checkpointID uint8) {
defer func() {
err := util.Save(lessonID, checkpointID)
if err != nil {
util.LogErrorAndExit(err)
}
}()

// TODO: find or develop a word wrapper.

fmt.Println(wordwrap.WrapString(
"Welcome to the activities program! This program was designed to interactively learn concepts"+
" within the terminal, as well as learning the terminal! To get started, first we'll learn basic"+
" Linux-based terminal concepts through the shell program.", util.WordWrapLimit))

fmt.Println("\nFirst, we'll ensure that you're running a shell-based command-line interpreter.")
if runtime.GOOS == "windows" {
fmt.Println(wordwrap.WrapString(
"\nWindows users should consider installing a version of MSYS2, the easiest way to get started"+
" with this is to use the Git Bash program from GitForWindows:\n"+
"https://git-scm.com/download/win", util.WordWrapLimit))
fmt.Println()
}
fmt.Println(wordwrap.WrapString(
"If you are running a non-windows based operating system, chances are that Git is already"+
" installed; to verify, enter \"git\" into your shell and you should see a lengthy dialog.",
util.WordWrapLimit))
fmt.Println()
fmt.Println(
"After installing Git, or to move on to the next checkpoint, simply re-run this program: `csa`")

},
ShouldPromote: func() bool {
switch os.Getenv("SHELL") {
case "/usr/bin/bash", "/usr/bin/zsh", "/usr/bin/sh":
return true
}
// for those who run other shells like fish, you could just use the env VALIDSHELL
return os.Getenv("VALIDSHELL") != ""
},
},
},
}
8 changes: 0 additions & 8 deletions lesson/two.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
package lesson

func init() {
err := Master.append(lessonTwo)
if err != nil {
panic(err)
}
}

var lessonTwo = &Lesson{
Id: 2,
Author: "Noah Mercedes",
Name: "Linux Filesystem Navigation and Manipulation",
Description: "Let's ditch file explorer and become hackers* B)",
Expand Down
36 changes: 19 additions & 17 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
package main

import "csclub-activities/cmd"
import (
"csclub-activities/cmd"
"csclub-activities/lesson"
"csclub-activities/util"
)

func main() {

cmd.Execute()

// Check if a checkpoint is active
//info, err := Load()
//if err != nil {
// if errors.Is(err, io.EOF) {
// err = NewSave()
// if err != nil {
// panic(err)
// }
// } else {
// panic(err)
// }
//}

// LF checkpoint
// util.Load could return an empty or new information struct.
// new does not help us.

information, err := util.Load()
if err != nil {
util.LogErrorAndExit(err)
}

err = lesson.Master.Run(int(information.LessonId), int(information.CheckpointID))
if err != nil {
util.LogErrorAndExit(err)
} else {
cmd.Execute()
}

// commands during lesson
// stop -> clears checkpoint
Expand Down
3 changes: 0 additions & 3 deletions util/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package util

import (
"encoding/binary"
"errors"
"os"
"time"
)
Expand All @@ -22,8 +21,6 @@ var fileName = UserHomeDir() + string(os.PathSeparator) + ".csclub_activities"

const NoOngoingActivity uint8 = 0

var ErrReservedIDs = errors.New("reserved lessonID or checkpointID value: cannot be 0")

func openCache() (*os.File, error) {
// 0666 -> r/w for all users
return os.OpenFile(fileName, os.O_CREATE|os.O_RDWR, 0666)
Expand Down
9 changes: 9 additions & 0 deletions util/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package util

import "errors"

var (
NonexistentLesson = errors.New("impossible index: nonexistent lesson")
NonexistentCheckpoint = errors.New("impossible index: nonexistent checkpoint")
ErrReservedIDs = errors.New("reserved lessonID or checkpointID value: cannot be 0")
)
2 changes: 2 additions & 0 deletions util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"runtime"
)

const WordWrapLimit = 100

// UserHomeDir https://github.com/spf13/viper/blob/e36638d8786b0b58231039fc6d7db32b904dd1ba/util.go#L140
func UserHomeDir() string {
if //goland:noinspection GoBoolExpressions
Expand Down

0 comments on commit 1fc7c25

Please sign in to comment.