<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <id>tag:www.refactormycode.com,2007:users1912</id>
  <link type="application/atom+xml" href="http://www.refactormycode.com/users/1912" rel="self"/>
  <title>jaewon.mp</title>
  <updated>Wed Feb 03 10:21:29 -0800 2010</updated>
  <entry>
    <id>tag:www.refactormycode.com,2007:Code1167</id>
    <published>2010-02-03T10:21:29-08:00</published>
    <updated>2010-02-03T10:21:29-08:00</updated>
    <title>[Haskell] Code from a novice Haskell user</title>
    <content type="html">&lt;p&gt;It's a simple command-line tool to read an XML file, get some data from it, convert them and append the converted data to a ma (Maya ascii) file.
&lt;br /&gt;This is the second program I've ever written in Haskell, so I think it would be far from good or ideal Haskell code. So I want some teachings from you about what can be improved &amp;amp; how things should be done in Haskell.&lt;/p&gt;

&lt;pre&gt;module Main where

import Text.XML.HaXml
import Text.XML.HaXml.Parse
import Text.XML.HaXml.Posn
import Text.XML.HaXml.Util
import System.Environment (getArgs)
import System.IO (IOMode(..), hClose, hGetContents, hPutStr, openFile)
import Data.List

main = do 
  args &amp;lt;- getArgs
  case args of
    [collada, ma] -&amp;gt; process collada ma
    _ -&amp;gt; argError
    
process :: String -&amp;gt; String -&amp;gt; IO ()  
process collada ma = do
  colladah &amp;lt;- openFile collada  ReadMode
  mah &amp;lt;- openFile ma ReadMode
  colladaStr &amp;lt;- hGetContents colladah
  maStr &amp;lt;- hGetContents mah
  
  -- Parse the COLLADA file and get the FOV animation data.
  let (Document _ _ root _) = xmlParse collada colladaStr
  let rootElem = CElem root noPos
  let animations = tag &amp;quot;COLLADA&amp;quot; /&amp;gt; tag &amp;quot;library_animations&amp;quot; /&amp;gt; tag &amp;quot;animation&amp;quot; $ rootElem
  let fovAnimation = (filter isFovAnimation animations) !! 0
  let sources = keep /&amp;gt; tag &amp;quot;source&amp;quot; /&amp;gt; tag &amp;quot;float_array&amp;quot; $ fovAnimation
  let times = map ((*24.0) . (read :: String -&amp;gt; Float)) $ words $ tagTextContent (sources !! 0)
  let values = map (yfovToFocalLength . (read :: String -&amp;gt; Float)) $ words $ tagTextContent (sources !! 1)
  let (CElem (Elem _ attributes _) _) = sources !! 0
  let (_, AttValue (Left countVal:_)) = attributes !! 0
  let count = read countVal :: Int
--putStrLn $ show count
--putStrLn $ show values
  
  -- Parse the ma file and get the name of the camera node.
  let createLine = (filter isCustomCameraCreate $ lines maStr) !! 0
  let !cameraName = takeWhile isNotQuote $ drop 1 $ dropWhile isNotQuote createLine
--putStrLn cameraName
  hClose mah
  
  -- Append the ma file with the FOV animation.
  mah2 &amp;lt;- openFile ma AppendMode
  let createNode = &amp;quot;createNode animCurveTU -n \&amp;quot;&amp;quot; ++ cameraName ++ &amp;quot;_focalLength\&amp;quot;;\n\tsetAttr \&amp;quot;.tan\&amp;quot; 10;\n\tsetAttr \&amp;quot;.wgt\&amp;quot; no;\n\tsetAttr -s &amp;quot; ++ (show count) ++ &amp;quot; \&amp;quot;.ktv[0:&amp;quot; ++ (show (count - 1)) ++ &amp;quot;]\&amp;quot; &amp;quot;
  hPutStr mah2 createNode
  hPutStr mah2 (concat $ map pairToString $ zip times values) 
  hPutStr mah2 &amp;quot;;\n&amp;quot;
  let connectAttr = &amp;quot;connectAttr \&amp;quot;&amp;quot; ++ cameraName ++ &amp;quot;_focalLength.o\&amp;quot; \&amp;quot;&amp;quot; ++ cameraName ++ &amp;quot;.fl\&amp;quot;;&amp;quot;
  hPutStr mah2 connectAttr
  
  hClose colladah
  hClose mah2

isFovAnimation animation = 
  let (CElem (Elem _ attributes _) _) = animation
  in let (_, AttValue (Left idStr:_)) = attributes !! 0
     in isSuffixOf &amp;quot;FOV&amp;quot; idStr

yfovToFocalLength yfov = yAperture / (tan (yfov * 0.5 * pi / 180.0) * 2.0)
                            where yAperture = 25.4 * 0.581
     
isCustomCameraCreate line = &amp;quot;createNode camera -n&amp;quot; `isPrefixOf` line

isNotQuote char = char /= '&amp;quot;'

pairToString pair = &amp;quot; &amp;quot; ++ (show . fst $ pair) ++ &amp;quot; &amp;quot; ++ (show . snd $ pair)

argError = putStrLn
  &amp;quot;Usage: add_fov_to_ma.exe COLLADA_filename ma_filename\n&amp;quot;&lt;/pre&gt;</content>
    <author>
      <name>jaewon.mp</name>
      <email>chimp@all2one.otherinbox.com</email>
    </author>
    <link type="text/html" href="http://www.refactormycode.com/codes/1167-code-from-a-novice-haskell-user" rel="alternate"/>
  </entry>
</feed>

