view src/entai_app/entai_app.go @ 46:6ec28d3c3e00

small changes.
author pyon@macmini
date Sat, 18 Apr 2020 21:10:29 +0900
parents f4ba4cfb09fd
children
line wrap: on
line source

/****************************************************************************/
/* Entai_app.go                                                             */
/*                                    Last Change: 2016-10-28 Fri 19:33:15. */
/*                                    By T.Mutoh                            */
/****************************************************************************/

package main

import (
    "bufio"
    "encoding/csv"
    "flag"
    "fmt"
    "io"
    "log"
    "net/http"
    "os"
    "strconv"
    "strings"
    "time"

    "entai"
)

var ver = "0.4"
var e entai.Entai

func main() {

    // arguments
    h := flag.Bool( "h", false, "help" )
    c := flag.String( "c", "", "config csv file" )
    r := flag.Bool( "r", false, "print rate" )
    b := flag.Bool( "b", false, "batch mode" )
    l := flag.Bool( "l", false, "1-liner mode" )
    v := flag.Bool( "v", false, "print verbose in 1-liner mode")
    i := flag.Bool( "i", false, "print input value in 1-liner mode")
    d := flag.Bool( "d", false, "intaracitve mode")
    s := flag.Bool( "s", false, "server mode" )
    p := flag.Int( "p", 8080, "listen port in server mode" )

    flag.Parse()

    if flag.NFlag() == 0 {
        printTile()
        flag.PrintDefaults()
        fmt.Fprint( os.Stderr, "\n" )
        os.Exit( 1 )
    }

    // Setting rates
    if *c == "" {
        e.DefaultRates()
    } else {
        f, err := os.Open( *c ); if err != nil {
            fmt.Fprintf( os.Stderr, "cannot open config-file : %v\n", err )
            os.Exit( 1 )
        }

        r := csv.NewReader( f )
        r.Comment = '#'
        r.TrimLeadingSpace = true
        for {
            record, err := r.Read()
            if err == io.EOF {
                break
            } else if err != nil {
                log.Fatal( err )
            }
            e.AddRates( record[1], record[2], record[3] )
        }
        f.Close()

    }

    switch {

    // Show examples
    case *h :
        printTile()
        fmt.Fprint( os.Stderr, "1-liner mode:\n" )
        fmt.Fprint( os.Stderr, "> entai_app -l 30000 20160731 20161224\n\n" )
        fmt.Fprint( os.Stderr, "> entai_app -i -l 29000 20160731 20161224\n\n" )
        fmt.Fprint( os.Stderr, "> entai_app -i -v -l 15000 20160731 20161224\n\n" )
        fmt.Fprint( os.Stderr, "> entai_app -c conf/entai.conf -l 15000 20160731 20161224\n\n" )
        fmt.Fprint( os.Stderr, "batch mode:\n" )
        fmt.Fprint( os.Stderr, "> entai_app -b 1.csv 2.csv ...\n\n" )
        fmt.Fprint( os.Stderr, "server mode:\n" )
        fmt.Fprint( os.Stderr, "> entai_app -s -p 3000\n" )
        os.Exit( 1 )

    // Show rates
    case *r :
        printTile()
		fmt.Fprint( os.Stderr, e.GetRates() )
        os.Exit( 0 )

    // Server-mode ( not implement )
    case *s :
        s := fmt.Sprintf( "localhost:%d", *p )
        http.HandleFunc( "/", httpHandler )
        log.Fatal( http.ListenAndServe( s, nil ) )

    // Intaractive-mode
    case *d :
        printTile()
		fmt.Print( e.GetRates() )
        fmt.Print( "-----------\n\n" )

        var t, d, p string
        for {
            t = getFromTerminal( "Input Tax ", t )
            d = getFromTerminal( "Input Due ", d )
            p = getFromTerminal( "Input Paid", p )

            result, detail, err := processEntai( t, d, p )
            if err != nil {
                fmt.Printf( "%v\n", err )
            }
            fmt.Printf( " = %d", result )

            fmt.Print( "\t\t\t... Continue [Enter] / Detail [1] / Quit [9] ? " )
            input := bufio.NewScanner( os.Stdin )
            input.Scan()
            switch input.Text() {
            case "1" :
                fmt.Printf( " = %s\n\n", detail )
            case "9" :
                os.Exit( 0 )
            default :
            }
        }

    // 1-Liner-mode
    case *l :
        p := flag.Arg(2)
        if p == "" {
            layout := "20060102"
            p = time.Now().Format( layout );
        }

        if *i {
            fmt.Printf( "%s,%s,%s,", flag.Arg(0), flag.Arg(1), p )
        }

		result, detail, err := processEntai( flag.Arg(0), flag.Arg(1), p )
        if err != nil {
			fmt.Fprintf( os.Stderr, "%s : %v\n", detail, err )
			os.Exit( 1 )
		}
        fmt.Print( result )

        if *v {
            fmt.Print( ",", detail )
        }
        fmt.Print( "\n" )

        os.Exit( 0 )

    // Batch-mode
    case *b :
        files := flag.Args()

        if len( files ) == 0 {
            fmt.Fprint( os.Stderr, "no input file.\n" )
            os.Exit( 1 )
        } else {

            for _, file := range files {
                f, err := os.Open( file ); if err != nil {
                    fmt.Fprintf( os.Stderr, "cannot open file.[%v]\n", err )
                    os.Exit( 1 )
                }

                input := bufio.NewScanner( f )
                b := bufio.NewWriter( os.Stdout )
                for input.Scan() {
                    s := strings.Split( input.Text(), "," )
					if strings.HasPrefix( input.Text(), "#" ) {
						if strings.Contains( input.Text(), "@@" ) {
							buf := strings.Replace( input.Text(), "#", "", 1 )
							buf  = strings.Replace( buf, "@@", "", 1 )
							fmt.Fprintf( b, "%s\n", buf )
						}
						continue
					}
					result, detail, err := processEntai( s[0], s[1], s[2] )
                    if err != nil {
						fmt.Fprintf( os.Stderr, "%s : %v\n", detail, err )
						os.Exit( 1 )
					}
					fmt.Fprintf( b, "%s,%s,%s,%d,%s\n", s[0], s[1], s[2], result, detail )
                }
                b.Flush()
                f.Close()
            }
            os.Exit( 0 )
        }
    }
}

// Subroutines
func processEntai( tax, due, paid string ) ( int, string, error ) {
	t, msg, err := validInt( tax ); if err != nil {
		return -1, msg, err
	}

	d, msg, err := validDate( due ); if err != nil {
		return -1, msg, err
	}
	p, msg, err := validDate( paid ); if err != nil {
		return -1, msg, err
	}

	e.Set( d, p, t )
	result, detail := e.Result()

	return result, detail, nil
}

func validDate( s string ) ( time.Time, string, error ) {
	layout := "20060102"
	t, err := time.Parse( layout, s ); if err != nil {
		return t, "bad date format.", err
	}
    return t, "", nil
}

func validInt( s string ) ( int, string, error ) {
	i, err := strconv.Atoi( s )
	if err != nil || i < 0 {
		return -1, "bad money format.", err
	}
    return i, "", nil
}

func getFromTerminal( prompt, last string ) ( string ) {
    fmt.Printf( "%s > ", prompt )
    input := bufio.NewScanner( os.Stdin )
    input.Scan()
    s := input.Text()
    if s == "." {
        s = last
        fmt.Printf( "%s > %s\n", prompt, s )
    }
    return s
}

func httpHandler( w http.ResponseWriter, r *http.Request ) {
    fmt.Fprintf( w, "RemoteAddr: %q\n", r.RemoteAddr )
    if err := r.ParseForm(); err != nil {
        log.Print( err )
    }
    for k, v := range r.Form {
        fmt.Fprintf( w, "%q: %q\n", k, v )
    }
}

func printTile() {
    fmt.Fprint(  os.Stderr, "\n==================================================\n" )
    fmt.Fprintf( os.Stderr, "  Entai_app ver %s ( 2016.10.19 ) - since 2016\n", ver  )
    fmt.Fprint(  os.Stderr, "==================================================\n\n" )
}