---
# System prepended metadata

title: Untitled

---

'''racket
#lang racket
(require csc151)
(require 2htdp/image)
(require rackunit)
(provide (all-defined-out))
(require csc151)

;;;csv->list

(define data
  (file->lines "csc151.csv"))

;;; (deletetitle dataset)->list?
;;; dataset : list?
;;; return a list w/o the titles, which is in the first line
(define deletetitle
  (lambda (dataset)
    (drop dataset 1)))

;;; (distribute dataset)->list?
;;; dataset : list?
;;; return a list that break every element in the list into smaller elements
(define distribute
  (lambda (dataset)
    (map (section string-split <> ",")  dataset)))

;;; (select dataset num)->list?
;;; dataset : list?
;;; num : number?
;;; return to a list of values under a specific title 
;;; (which is represented by a number temporarily) in the spreadsheet
(define select
  (lambda (dataset num)
    (map (section list-ref <> num) (distribute dataset))))

(define titles (make-hash))

;;; (name-it/helper data location)->hash table？
;;; data : list?
;;; location : number?
;;; return to build a library that stores every spreadsheet's titles' number
(define name-it/helper
  (lambda (data location)
    (when (not (null? data))
      (hash-set! titles (car data) location)
      (name-it/helper (cdr data) (+ location 1)))))

;;; (name-it data)->hash table?
;;; data : list?
;;; return to build a library that stores every spreadsheet's titles' number
;;; while the number start from 0
(define name-it
  (lambda (data)
    (name-it/helper data 0)))

;;; (2var/helper dataset num1 num2)->list？
;;; dataset : list?
;;; num1 : number?
;;; num2 : number?
;;; select all the numbers in one title (temporaily use num1 to represent)
;;; and select all the numbers in another title (temporaily use num2 to represent)
;;; then combining these two set of values by pairs with a sub-list
(define 2var/helper
  (lambda (dataset num1 num2)
    (let* ([var1 (select (deletetitle dataset) num1)]
           [var2 (select (deletetitle dataset) num2)])
      (if (equal? '() var1)
          null
          (append (2var/helper (drop dataset 1) num1 num2) (list (list (car var1) (car var2))))))))

;;; (2var dataset col1 col2)->list?
;;; dataset : list?
;;; col1 : string?
;;; col2 : string?
;;; select all the numbers in one title, namely col1
;;; and select all the numbers in another title, namely col2
;;; then combining these two set of values by pairs with a sub-list
(define 2var
  (lambda (dataset col1 col2)
    (let* ([name-hash (name-it (car (distribute dataset)))]
           [num1 (hash-ref titles col1)]
           [num2 (hash-ref titles col2)])
      (2var/helper dataset num1 num2))))

;;;/


;;;scatterplot

;;; (my-string->number str) -> number? or false?
;;;   str : string?
;;; Converts str to a number.  If str is empty, returns 0.  If str is not
;;; a number, returns #f.
(define my-string->number
  (lambda (str)
    (if (equal? str "")
        0
        (string->number str))))

;;; (background col1 col2 dataset)->graph?
;;; col1 : string?
;;; col2 : string?
;;; dataset : list?
;;; return a graph that serves as the background of the scatterplot
(define background
  (lambda (col1 col2 dataset)
    (let*
        ([col1list (map (section car <>) (2var data col1 col2))]
         [col2list (map (section cadr <>) (2var data col1 col2))]
         [col1num (map my-string->number col1list)]
         [col2num (map my-string->number col1list)]
         [col1max (apply max col1num)]
         [col2max (apply max col2num)]
         [col1min (apply min col1num)]
         [col2min (apply min col2num)]
         [col1val (- col1max col1min)]
         [col2val (- col2max col2min)]
         [xaxis (+ (* 10 col1val) col1val)]
         [yaxis (+ (* 10 col2val) col1val)])
      (rectangle xaxis yaxis 'outline "black"))))

(define point (circle 1 'solid "black"))

;;; (scatterpoint x y back col1 col2 dataset)->graph?
;;; x : number?
;;; y : number?
;;; back : graph?
;;; col1 : string?
;;; col2 : string?
;;; dataset : list?
;;; return to a graph that add scatterpoint to the background
(define scatterpoint
  (lambda (x y back col1 col2 dataset)
    (let*
        ([col1list (map (section car <>) (2var data col1 col2))]
         [col2list (map (section cadr <>) (2var data col1 col2))]
         [col1num (map my-string->number col1list)]
         [col2num (map my-string->number col1list)]
         [col1max (apply max col1num)]
         [col2max (apply max col2num)]
         [col1min (apply min col1num)]
         [col2min (apply min col2num)]
         [col1val (- col1max col1min)]
         [col2val (- col2max col2min)]
         [xaxis (+ (* 10 col1val) col1val)]
         [yaxis (+ (* 10 col2val) col1val)])
      (overlay/offset point
                      (- (- (+ (/ col1val 2) (* 10 (- x col1min)))) (/ (+ xaxis (/ col1val 2)) -2))
                      (- (+ (/ col1val 2) (* y 10)) (/ yaxis 2))
                      back))))

;;; (scatterplot/helper lst so-far col1 col2 dataset)->graph？
;;; lst : list?
;;; so-far ： graph?
;;; col1 : string?
;;; col2 : string?
;;; dataset : list?
;;; return to a graph that add all the scatterpoints into the background
(define scatterplot/helper
  (lambda (lst so-far col1 col2 dataset)
    (if (null? lst)
        so-far
        (let([first (car lst)])
          (scatterplot/helper (cdr lst) (scatterpoint (my-string->number (car first)) (my-string->number (cadr first)) so-far col1 col2 dataset) col1 col2 dataset)))))

;;; (scatterplot dataset col1 col2)->graph？
;;; dataset : list?
;;; col1 : string?
;;; col2 : string?
;;; return to a graph that add all the scatterpoints into the background
(define scatterplot
  (lambda (dataset col1 col2)
    (scatterplot/helper (2var dataset col1 col2) (background col1 col2 dataset) col1 col2 dataset)))

;;;/


;;;bar graph

;; (bar h color) -> image?
;; h: number?
;; color: symbol?
;; Return the result of the bar shape
(define bar
  (lambda (h color)
    (rectangle 40 h 'solid color)))

;; (frame-color color) -> symbol?
;; color: symbol?
;; Return corresponding symbol based on condition
(define frame-color
  (lambda (color)
    (if (>=
         (/
          (+
           (red-component color)
           (green-component color)
           (blue-component color)) 3) 127)
        'black
        'transparent)))

;; (frame h) -> number?
;; h: number?
;; color: symbol?
;; Return the result of the frame shape with set height
(define frame
  (lambda (h color)
    (rectangle 40 h 'outline (frame-color color))))

;; (blank) -> image?
;; Return the result of the blank shape with set height, shape, width, colors
(define blank
  (rectangle 5 2 'solid "white"))

;; (label label) -> image?
;; return the text with string in label with 12 size and black color
(define label-
  (lambda (label)
    (text label 12 "black")))

;; (num num color) -> image?
;; num -> number?
;; color -> symbol?
;; return the number with 10 size and certain color
(define num
  (lambda (num color)
    (text (number->string num) 10 color)))

;; (short-blank)-> image?
;; return the number with certain color, length, and width
(define short-blank
  (rectangle 10 5 'solid "white"))

;; (num-color color) -> string?
;; color -> symbol?
;; return the color based on the condition
(define num-color
  (lambda (color)
    (if (>=
         (/
          (+
           (red-component color)
           (green-component color)
           (blue-component color)) 3) 127)
        "black"
        "white")))

;; (one-unity height label num-bar num-one num-the-other color) -> graph?
;; height: number?
;; label: string?
;; num-bar: number?
;; num-one: number?
;; num-the-other: number?
;; color: symbol?
;; Return the graph
(define one-unity
  (lambda (height label num-bar num-one num-the-other color)
    (above
     (overlay (num num-bar (num-color color))
              (frame (* height (/ num-bar (max num-one num-the-other num-bar))) color)
              (bar (* height (/ num-bar (max num-one num-the-other num-bar))) color))
     short-blank
     (label- label))))

;; (error-bar1) -> graph?
;;   l -> real?
;; return the error bar with calculated length
(define error-bar1
  (lambda (l)
    (above/align "middle"
                 (rectangle 15 1 'solid 'red)
                 (rectangle 1 (* l 50) 'solid 'red)
                 (rectangle 5 1 'solid 'red))))

(define error-bar2
  (lambda (l)
    (above/align "middle"
                 (rectangle 5 1 'solid 'red)
                 (rectangle 1 (* l 50) 'solid 'red)
                 (rectangle 15 1 'solid 'red))))

;; (bar-chart height label1 num1 color1 label2 num2 color2 label3 num3 color3)-> image?
;; height -> number?
;; label1 -> string?
;; num1 -> number?
;; color1 -> string?
;; label2 -> string
;; num2 -> number?
;; color2 -> string?
;; label3 -> string
;; num3 -> number?
;; color3 -> string?
;; l -> real?
;; return the total bar-chart image based on the condition
(define bar-chart
  (lambda (height label1 num1 color1 label2 num2 color2 label3 num3 color3 label4 num4 color4)
    (beside/align 'bottom
                  (above/align "middle"
                               (error-bar1 0.210818511)
                               (overlay/align  "middle" "top"
                                               (error-bar2 0.210818511)
                                               (one-unity height label1 num1 num2 num3 color1)))
                  blank
                  (above/align "middle"
                               (error-bar1 0.20203030509)
                               (overlay/align  "middle" "top"
                                               (error-bar2 0.20203030509)
                                               (one-unity height label2 num2 num1 num3 color2)))
                  blank
                  (above/align "middle"
                               (error-bar1 0.145643816)
                               (overlay/align  "middle" "top"
                                               (error-bar2 0.145643816)
                                               (one-unity height label3 num3 num1 num2 color3)))
                  blank
                  (above/align "middle"
                               (error-bar1 0.158910432)
                               (overlay/align  "middle" "top"
                                               (error-bar2 0.158910432)
                                               (one-unity height label4 num4 num1 num2 color4))))))

;;; (tags hash catvar)->hashatble
;;; hash: hash?
;;; catvar: string?
;;; input the hash and the string return the empty list
(define tags
  (lambda (hash catvar)
    (hash-ref hash catvar '())))

;;; (tag! hash catvar convar)->hashset?
;;; hash: hash?
;;; catvar: string?
;;; convar: number?
;;; return the hash table with many values in a list
(define tag!
  (lambda (hash catvar convar)
    (hash-set! hash catvar (cons convar (tags hash catvar)))))

(define make-graph (make-hash))

;;; (hash-list lst)-> hashset?
;;; lst: a short list that contains two element?
;;; return the hashtable where the first element is the ;;; key and the second element is the value
(define hash-list
  (lambda (lst)
    (let ([catvar (car lst)]
          [convar (cadr lst)])
      (tag! make-graph catvar convar))))

;;; (hash-for-all lst)->hashset
;;; lst: listof lists?
;;; return the hashtable that input a list of lists with 2 elements.
(define hash-for-all
  (lambda (lst)
      (when (not (null? lst))
        (hash-list (car lst)) 
        (hash-for-all (cdr lst)))))


(define hash-for-dataset
  (lambda (dataset catvar convar)
    (let ([lst (2var dataset catvar convar)])
      (map hash-for-all lst))))

(define catvar-list/helper
  (lambda (lst)
    (cond
      [(number? (car lst))
       (cadr lst)]
      [(number? (cadr lst))
       (car lst)])))

(define catvar-list
  (lambda (lst)
    (append (map catvar-list/helper lst))))
;
;(define median
;  (lambda (lst)
;    (and (hash-for-all lst) (hash-ref (???)))))



;;(define hash-list-2
;;  (lambda (lst)
;;    (map (section tag! hash str <>) ())))

(define 3.5-4
  '(1 0 0 0 1 0))

(define 4-4.5
  '(1 0 0 1 0 0 1))

(define 4.5-5
  '(0 0 0 0 1 1 0 0 1 0 0))

(define 5+
  '(1 0 0 0 1 1 0 1 0 1 0))

(define helper
  (lambda (lst)
    (/(length (filter (section equal? 1 <>) lst)) (length lst))))

(define 3.5-4success
  (helper 3.5-4))

(define 4-4.5success
  (helper 4-4.5))

(define 4.5-5success
  (helper 4.5-5))

(define 5+success
  (helper 5+))

(define cscbar
  (bar-chart 120 "3.5-4success" 3.5-4success 'blue "4-4.5success" 4-4.5success 'blue "4.5-5success" 4.5-5success 'blue "5+success" 5+success 'blue))

;;;/

;;; final image generation

;;; (auto-choose dataset col1 col2)->
(define auto-choose
  (lambda (dataset col1 col2)
    (let* ([col1list (map (section car <>) (2var data col1 col2))]
           [col2list (map (section cadr <>) (2var data col1 col2))]
           [col1num (map my-string->number col1list)]
           [col2num (map my-string->number col2list)])
      (cond
        [(and (andmap false? col1num) (andmap false? col2num))
         (error "we cannot make graph with two categorical variables")]
        [(and (andmap number? col1num) (andmap number? col2num) #t)
         (scatterplot dataset col1 col2)]
        [(and (andmap false? col1num) (andmap number? col2num) #t)
         "(barchart dataset col1 col2)"]
        [(and (andmap number? col1num)(andmap false? col2num) #t)
         "(barchart dataset col2 col1)"]
        [else
         (error "the form doesn't follow what we want")]))))

(define save
  (lambda (dataset col1 col2 filename)
    (save-image auto-choose filename)))
'''