Advertisement
Guest User

server go

a guest
May 12th, 2019
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 9.63 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4.     "database/sql"
  5.     "flag"
  6.     "fmt"
  7.     "log"
  8.     "net/http"
  9.     "os"
  10.     "os/exec"
  11.     "strconv"
  12.     "time"
  13.  
  14.     "bytes"
  15.     "github.com/gorilla/websocket"
  16.     _ "github.com/lib/pq"
  17.     "strings"
  18. )
  19.  
  20. // set database connection parameters
  21. const (
  22.     host     = "localhost"
  23.     port     = 5432
  24.     user     = "postgres"
  25.     password = "rootpost"
  26.     dbname   = "GoCompiler"
  27. )
  28.  
  29. // Code Table database schema
  30. type Code struct {
  31.     id     int
  32.     date   string
  33.     code   string
  34.     result string
  35.     name   string
  36. }
  37.  
  38. // set server address
  39. var addr = flag.String("addr", "192.168.0.17:8080", "http service address")
  40.  
  41. // http upgrader initialization
  42. var upgrader = websocket.Upgrader{} // use default options
  43.  
  44. // connection function
  45. func echo(w http.ResponseWriter, r *http.Request) {
  46.  
  47.     //upgrades server connection to the websocket
  48.     c, err := upgrader.Upgrade(w, r, nil)
  49.     if err != nil {
  50.         log.Print("upgrade:", err)
  51.         return
  52.     }
  53.  
  54.     // print client address
  55.     fmt.Println("REQUEST OCCURED: " + c.RemoteAddr().String())
  56.  
  57.     defer c.Close()
  58.     for {
  59.         // read the message from client
  60.         mt, message, err := c.ReadMessage()
  61.         if err != nil {
  62.             log.Println("read:", err)
  63.             break
  64.         }
  65.         log.Printf("recv: %s", message)
  66.  
  67.         // set file name as client address
  68.         fileName := "data" + c.RemoteAddr().String()
  69.  
  70.         //write received code to file
  71.         f, err := os.Create(fileName + ".go")
  72.         n2, err := f.Write(message)
  73.         f.Sync()
  74.         f.Close()
  75.         log.Printf("wrote %d bytes\n", n2)
  76.  
  77.         //execute file:
  78.         execStatus, execResult := FileExecute(fileName)
  79.  
  80.         if !execStatus {
  81.             //send failure message to client
  82.             err = c.WriteMessage(mt, []byte("NOK"))
  83.             if err != nil {
  84.                 log.Println(" write:", err)
  85.                 break
  86.             }
  87.         } else {
  88.             //send success message to client
  89.             err = c.WriteMessage(mt, []byte("OK"))
  90.             if err != nil {
  91.                 log.Println(" write:", err)
  92.                 break
  93.             }
  94.             //send program output to client
  95.             err = c.WriteMessage(mt, []byte(execResult))
  96.             if err != nil {
  97.                 log.Println(" write:", err)
  98.                 break
  99.             }
  100.             // generate comparison report
  101.             raport := insertToDatabase(string(message), string(execResult), string(fileName))
  102.             //send report output to client
  103.             err = c.WriteMessage(mt, []byte(raport))
  104.             if err != nil {
  105.                 log.Println(" write:", err)
  106.                 break
  107.             }
  108.         }
  109.     }
  110. }
  111.  
  112. func FileExecute(fileName string) (bool, string) {
  113.     //command line program execution
  114.     cmd := exec.Command("cmd", "/C", "go run", fileName+".go")
  115.  
  116.     // program output reading
  117.     out, err := cmd.CombinedOutput()
  118.     if err != nil {
  119.         return false, ""
  120.     }
  121.     log.Printf("combined out:\n%s\n", string(out))
  122.  
  123.     // writing output to file
  124.     f, err := os.Create(fileName + ".txt")
  125.     n2, err := f.Write(out)
  126.     f.Sync()
  127.     f.Close()
  128.     log.Printf("wrote %d bytes\n", n2)
  129.  
  130.     // output return
  131.     return true, string(out)
  132. }
  133.  
  134. func insertToDatabase(codee string, resultt string, namee string) string {
  135.  
  136.     // database parameters concatenation
  137.     psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+
  138.         "password=%s dbname=%s sslmode=disable",
  139.         host, port, user, password, dbname)
  140.  
  141.     // database open  connection
  142.     db, err := sql.Open("postgres", psqlInfo)
  143.     if err != nil {
  144.         panic(err)
  145.     }
  146.     defer db.Close()
  147.  
  148.     // ping database to check if connection established
  149.     err = db.Ping()
  150.     if err != nil {
  151.         panic(err)
  152.     }
  153.  
  154.     // read current time
  155.     currentTime := time.Now()
  156.     time := currentTime.String()
  157.  
  158.     fmt.Println("Successfully connected!")
  159.  
  160.     // database insert execution
  161.     sqlInsert := `
  162.     INSERT INTO public."Code" (date,code,result,name)
  163.     VALUES ($1, $2 , $3, $4)`
  164.     _, err = db.Exec(sqlInsert, time, codee, resultt, namee)
  165.     if err != nil {
  166.         panic(err)
  167.     }
  168.     // save current code object
  169.     codeObject := Code{name: namee,
  170.         date:   time,
  171.         result: resultt,
  172.         code:   codee}
  173.  
  174.     return selectFromDatabase(db, err, codeObject)
  175.  
  176. }
  177.  
  178. func selectFromDatabase(db *sql.DB, err error, codeObject Code) string {
  179.     var codes []Code
  180.     var code Code
  181.     //databse select execution
  182.     sqlSelect := `SELECT * FROM public."Code"`
  183.     rows, row := db.Query(sqlSelect)
  184.     // loop throw received records
  185.     for rows.Next() {
  186.         errs := rows.Scan(&code.id, &code.date, &code.code,
  187.             &code.result, &code.name)
  188.         if err != nil {
  189.             panic(err)
  190.             fmt.Println(row)
  191.             fmt.Println(errs)
  192.  
  193.         }
  194.         // append object to objects array
  195.         codes = append(codes, Code{id: code.id,
  196.             date:   code.date,
  197.             code:   code.code,
  198.             result: code.result,
  199.             name:   code.name})
  200.     }
  201.  
  202.     return compareData(codes, codeObject)
  203. }
  204.  
  205. func compareData(codes []Code, codeObject Code) string {
  206.     raport := " "
  207.     raports := " "
  208.     percentage := 0
  209.     // loop throw array of code objects
  210.     for index, element := range codes {
  211.         //ignore the last code object
  212.         if element.date != codeObject.date {
  213.             //get difference and percentage
  214.             raport, percentage = Diff(string(element.code), string(codeObject.code))
  215.             raports += "\n Procentowa zgodnosc aktualnego pliku z plikiem z : " + element.date + " wynosi: " + strconv.Itoa(percentage) + "% \n" + "Roznice plikow: \n" + raport
  216.         }
  217.         fmt.Printf(string(index))
  218.     }
  219.  
  220.     return raports
  221. }
  222.  
  223. // return difference and percentage similarity
  224. func Diff(A, B string) (string, int) {
  225.  
  226.     aLines := strings.Split(A, "\n")
  227.     bLines := strings.Split(B, "\n")
  228.  
  229.     chunks := DiffChunks(aLines, bLines)
  230.     equalSum := 1
  231.     addedSum := 0
  232.     deletedSum := 0
  233.  
  234.     buf := new(bytes.Buffer)
  235.     for _, c := range chunks {
  236.         for _, line := range c.Added {
  237.             addedSum += 1
  238.             fmt.Fprintf(buf, "+%s\n", line)
  239.         }
  240.         for _, line := range c.Deleted {
  241.             deletedSum += 1
  242.             fmt.Fprintf(buf, "-%s\n", line)
  243.         }
  244.         for _, line := range c.Equal {
  245.             equalSum += 1
  246.             fmt.Fprintf(buf, " %s\n", line)
  247.         }
  248.     }
  249.  
  250.     equalPercent := (equalSum * 100) / (equalSum + addedSum + deletedSum)
  251.     return strings.TrimRight(buf.String(), "\n"), equalPercent
  252. }
  253.  
  254. // library method for difference calculation
  255. func DiffChunks(a, b []string) []Chunk {
  256.     // algorithm: http://www.xmailserver.org/diff2.pdf
  257.  
  258.     // We'll need these quantities a lot.
  259.     alen, blen := len(a), len(b) // M, N
  260.  
  261.     // At most, it will require len(a) deletions and len(b) additions
  262.     // to transform a into b.
  263.     maxPath := alen + blen // MAX
  264.     if maxPath == 0 {
  265.         // degenerate case: two empty lists are the same
  266.         return nil
  267.     }
  268.  
  269.     // Store the endpoint of the path for diagonals.
  270.     // We store only the a index, because the b index on any diagonal
  271.     // (which we know during the loop below) is aidx-diag.
  272.     // endpoint[maxPath] represents the 0 diagonal.
  273.     //
  274.     // Stated differently:
  275.     // endpoint[d] contains the aidx of a furthest reaching path in diagonal d
  276.     endpoint := make([]int, 2*maxPath+1) // V
  277.  
  278.     saved := make([][]int, 0, 8) // Vs
  279.     save := func() {
  280.         dup := make([]int, len(endpoint))
  281.         copy(dup, endpoint)
  282.         saved = append(saved, dup)
  283.     }
  284.  
  285.     var editDistance int // D
  286. dLoop:
  287.     for editDistance = 0; editDistance <= maxPath; editDistance++ {
  288.         // The 0 diag(onal) represents equality of a and b.  Each diagonal to
  289.         // the left is numbered one lower, to the right is one higher, from
  290.         // -alen to +blen.  Negative diagonals favor differences from a,
  291.         // positive diagonals favor differences from b.  The edit distance to a
  292.         // diagonal d cannot be shorter than d itself.
  293.         //
  294.         // The iterations of this loop cover either odds or evens, but not both,
  295.         // If odd indices are inputs, even indices are outputs and vice versa.
  296.         for diag := -editDistance; diag <= editDistance; diag += 2 { // k
  297.             var aidx int // x
  298.             switch {
  299.             case diag == -editDistance:
  300.                 // This is a new diagonal; copy from previous iter
  301.                 aidx = endpoint[maxPath-editDistance+1] + 0
  302.             case diag == editDistance:
  303.                 // This is a new diagonal; copy from previous iter
  304.                 aidx = endpoint[maxPath+editDistance-1] + 1
  305.             case endpoint[maxPath+diag+1] > endpoint[maxPath+diag-1]:
  306.                 // diagonal d+1 was farther along, so use that
  307.                 aidx = endpoint[maxPath+diag+1] + 0
  308.             default:
  309.                 // diagonal d-1 was farther (or the same), so use that
  310.                 aidx = endpoint[maxPath+diag-1] + 1
  311.             }
  312.             // On diagonal d, we can compute bidx from aidx.
  313.             bidx := aidx - diag // y
  314.             // See how far we can go on this diagonal before we find a difference.
  315.             for aidx < alen && bidx < blen && a[aidx] == b[bidx] {
  316.                 aidx++
  317.                 bidx++
  318.             }
  319.             // Store the end of the current edit chain.
  320.             endpoint[maxPath+diag] = aidx
  321.             // If we've found the end of both inputs, we're done!
  322.             if aidx >= alen && bidx >= blen {
  323.                 save() // save the final path
  324.                 break dLoop
  325.             }
  326.         }
  327.         save() // save the current path
  328.     }
  329.     if editDistance == 0 {
  330.         return nil
  331.     }
  332.     chunks := make([]Chunk, editDistance+1)
  333.  
  334.     x, y := alen, blen
  335.     for d := editDistance; d > 0; d-- {
  336.         endpoint := saved[d]
  337.         diag := x - y
  338.         insert := diag == -d || (diag != d && endpoint[maxPath+diag-1] < endpoint[maxPath+diag+1])
  339.  
  340.         x1 := endpoint[maxPath+diag]
  341.         var x0, xM, kk int
  342.         if insert {
  343.             kk = diag + 1
  344.             x0 = endpoint[maxPath+kk]
  345.             xM = x0
  346.         } else {
  347.             kk = diag - 1
  348.             x0 = endpoint[maxPath+kk]
  349.             xM = x0 + 1
  350.         }
  351.         y0 := x0 - kk
  352.  
  353.         var c Chunk
  354.         if insert {
  355.             c.Added = b[y0:][:1]
  356.         } else {
  357.             c.Deleted = a[x0:][:1]
  358.         }
  359.         if xM < x1 {
  360.             c.Equal = a[xM:][:x1-xM]
  361.         }
  362.  
  363.         x, y = x0, y0
  364.         chunks[d] = c
  365.     }
  366.     if x > 0 {
  367.         chunks[0].Equal = a[:x]
  368.     }
  369.     if chunks[0].empty() {
  370.         chunks = chunks[1:]
  371.     }
  372.     if len(chunks) == 0 {
  373.         return nil
  374.     }
  375.     return chunks
  376. }
  377.  
  378. type Chunk struct {
  379.     Added   []string
  380.     Deleted []string
  381.     Equal   []string
  382. }
  383.  
  384. func (c *Chunk) empty() bool {
  385.     return len(c.Added) == 0 && len(c.Deleted) == 0 && len(c.Equal) == 0
  386. }
  387.  
  388. func main() {
  389.     flag.Parse()
  390.     log.SetFlags(0)
  391.     log.Printf("Server Listening")
  392.     //request handler
  393.     http.HandleFunc("/echo", echo)
  394.     log.Fatal(http.ListenAndServe(*addr, nil))
  395.  
  396. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement