packages feed

schedevr-0.1.0.4: src/prog_graph/WatchEVR.hs

module WatchEVR (
	idPoint', dayId, accumSecond, dayPoint, getConverter, progPercent,
	waku, chart, fontsize, getPoint
) where

import Graphics.X11.Turtle
import Data.List
import Data.Time
import Data.Maybe
import Control.Arrow
import System.Environment
import System.FilePath
import Data.Char

evrItemsName, evrScheduleName, evrProgressName :: FilePath
-- evrItemsName = "evr_items.txt"
evrItemsName = "item_list"
evrScheduleName = "evr_schedule"
evrProgressName = "progress"

main :: IO ()
main = do
	prog <- getProgName
	path <- getExecutablePath
	let dir = takeDirectory path ++ "/"
	eiCnt <- readFile $ dir ++ evrItemsName
	esCnt <- readFile $ dir ++ evrScheduleName
	espCnt <- readFile $ dir ++ evrProgressName
	let
--		ei = map idPoint $ tail $
--			dropWhile (not . isPrefixOf "* タイトル") $ lines eiCnt
		ei = map idPoint' $ lines eiCnt
		es = map dayId $ lines esCnt
		esp = map dayId $ lines espCnt
		di = accumSecond (+) 0 $ dayPoint ei es
		dip = accumSecond (+) 0 $ dayPoint ei esp
		cnv = getConverter (50, 100) (400, 200) di
		pc = progPercent dip di
	f <- openField
	topleft f
	t <- newTurtle f
	speed t "fastest"
	flushoff t
	waku t (50, 100) (400, 200) di
	goto t 50 300
	flushon t
	speed t "slowest"
	chart t "grey" cnv (50, 100) (400, 200) di
	speed t "slow"
	goto t 50 300
	speed t "slowest"
	chart t "black" cnv (50, 100) (400, 200) dip
	speed t "fastest"
	goto t 200 100
	write t "Kochi Gothic" fontsize $ take 4 (show pc) ++ "%"
	hideturtle t
	onkeypress f $ return . (/= 'q')
	waitField f

progPercent :: [(Day, Int)] -> [(Day, Int)] -> Double
progPercent p s = 100 *
	fromIntegral (getPoint p) / fromIntegral (getPoint s)

getPoint :: [(Day, Int)] -> Int
getPoint = snd . last

idPoint :: String -> (String, Int)
idPoint ln = (i, read $ dropWhile (== '\t') p)
	where
	(i, p) = span (/= '\t') $ dropWhile (== '\t') $ dropWhile (/= '\t') ln

idPoint' :: String -> (String, Int)
idPoint' str = (is !! 0, read $ is !! 1)
	where
	is = split ':' str

split :: Char -> String -> [String]
split _ "" = []
split c str = case span (/= c) str of
	(s, "") -> [deleteSpaces s]
	(s, _ : r) -> deleteSpaces s : split c r

deleteSpaces :: String -> String
deleteSpaces = reverse . dropWhile isSpace . reverse . dropWhile isSpace

dayId :: String -> (Day, String)
dayId ln = (read d, i)
	where
	(i, d) = span (/= '\t') ln

dayPoint :: [(String, Int)] -> [(Day, String)] -> [(Day, Int)]
dayPoint tbl = map $ second $ fromJust . flip lookup tbl

accumSecond :: (c -> b -> c) -> c -> [(a, b)] -> [(a, c)]
accumSecond op r0 [] = []
accumSecond op r0 ((x1, y1) : ps) =
	(x1, r0 `op` y1) : accumSecond op (r0 `op` y1) ps

fontsize = 10

chart :: (Enum x, Enum y, Ord x, Show x, ColorClass c) => Turtle -> c ->
	((x, y) -> (Double, Double)) ->
	(Double, Double) -> (Double, Double) -> [(x, y)] -> IO ()
chart t c converter tl@(left, top) wh@(width, height) dt = do
	pencolor t c
	turtleChart t $ map converter dt
	penup t

waku t tl@(left, top) wh@(width, height) dt = do
		penup t
		goto t left (top + height)
		pendown t
		goto t (left + width) (top + height)
		penup t
		goto t left (top + height)
		pendown t
		goto t left top
		penup t
		goto t (left - fontsize * 2) (top + height + fontsize * 1.5)
		write t "Kochi Gothic" fontsize $ show minx
		goto t (left + width - fontsize * 2) (top + height + fontsize * 1.5)
		write t "Kochi Gothic" fontsize $ show maxx
	where
	minx = minimum $ map fst dt
	maxx = maximum $ map fst dt

turtleChart :: Turtle -> [(Double, Double)] -> IO ()
turtleChart t ((x0, y0) : ps) = do
	penup t
	goto t x0 y0
	pendown t
	mapM_ (uncurry $ goto t) ps

getConverter :: (Enum x, Enum y) => (Double, Double) -> (Double, Double) ->
	[(x, y)] -> (x, y) -> (Double, Double)
getConverter (left, top) (width, height) ps = convertx *** converty
	where
	maxx = maximum $ map (fromEnum . fst) ps
	minx = minimum $ map (fromEnum . fst) ps
	maxy = maximum $ map (fromEnum . snd) ps
	miny = minimum $ map (fromEnum . snd) ps
	convertx x = left +
		(fromIntegral $ fromEnum x - minx) /
		(fromIntegral $ maxx - minx) * width
	converty y = top + height -
		(fromIntegral $ fromEnum y - miny) /
		(fromIntegral $ maxy - miny) * height