F#代码——天气预报

这个是很早很早之前作的一个小东西,不过由于工作时间原因,没能做好,留个笔记:

// Learn more about F# at http://fsharp.net

//namespace WeatherDemo
#if INTERACTIVE
#r @"C:\Program Files\Reference Assemblies\Microsoft\FSharp\3.0\Runtime\v4.0\Type Providers\FSharp.Data.TypeProviders.dll"
#r @"C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\Profile\Client\System.ServiceModel.dll"
#r "System.XML.Linq.dll"
#r "System.Xml.dll"
#endif

open Microsoft.FSharp.Data.TypeProviders
open System.ServiceModel
open System.Xml.Linq
open System.ServiceModel.Channels
open System.ServiceModel.Dispatcher
open System
open System.Text
open System.Xml
open System.Xml.Serialization
open System.IO
open System.Collections.Generic



type TPmap =  Microsoft.FSharp.Data.TypeProviders.WsdlService<ServiceUri = "http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl">
type port = TPmap.ServiceTypes.ndfdXMLPortType

type GetWeather() =
     //Bug : 260425 [DotCompletion]Dotcompletion doesn't work for the code after keyword inherit
    //inherit Microsoft

    //Bug : 265164 [DotCompletion]Incompleted completionlist showed while going back to get the list using shortkey
    let client = new TPmap.ServiceTypes.ndfdXMLPortTypeClient()
         
    // A bounch of default argument
    let m_timeSeries =  TPmap.ServiceTypes.productType.timeseries
    let m_ss = TPmap.ServiceTypes.productType()
    let m_startTime = System.DateTime.Now
    let m_endTime = System.DateTime.Now.AddDays(1.0)
    let m_weatherParam = new TPmap.ServiceTypes.weatherParametersType()
    let m_product = new TPmap.ServiceTypes.productType()
    let m_SetDefaultArg =
        m_weatherParam.maxt <- true
        m_weatherParam.mint <- true
        m_weatherParam.temp <- true
        m_weatherParam.sky  <- true
        m_weatherParam.appt <- true
        m_weatherParam.conhazo <- true
        m_weatherParam.dew <- true
        m_weatherParam.icons <- true

    // Parse data from the XML String which retured by NWS .
    let ParseSpecifyNodeFromXMLString(srcData : string, specifiedNode : string) =                     
        let xName = XName.Get(specifiedNode)        
        
        //Get all the children Elements of root . Transfer the Seq to List
        let childToList =
            srcData
                |> XDocument.Parse
                |> fun xDoc -> xDoc.Root
                |> fun rootElement -> rootElement.Elements()
                |> Seq.toList    
        
        // Define a specific transfer function , used in the rec function.
        let seqTolist (srcElement : XElement) =
            let childElementsList =  
                srcElement 
                        |> fun x -> x.Elements()
                        |> fun xSeq -> (xSeq |> Seq.toList)
            childElementsList                   
        
        //Used to store the result in for loop
        let (resultList : list<XElement> ref) = ref []
        
        //Rec function used to get the specific XElement by given XName
        let rec selecteElement (dataList : list<XElement>) =              
            for element in dataList do               
                if (element.HasElements = true) then
                    match element with
                    | _ when element.Name = xName ->
                            resultList := List.append ([element]) !resultList
                            printfn ""
                    | _ ->                             
                            element |> seqTolist
                                    |> selecteElement 
                      
        selecteElement childToList
        !resultList

    // This funciton is used to convert the string to ISO-8895-1
    let convertStrToIso (str : string) =
        // BUgs here
        let ``Unicode`` = System.Text.Encoding.Unicode
        let unicodeBytes = ``Unicode``.GetBytes(str)
        let unicodeStr = ``Unicode``.GetString(unicodeBytes)

        let ``iso-8859-1`` = System.Text.Encoding.GetEncoding("iso-8859-1")
        let isoBytes = ``iso-8859-1``.GetBytes(str)
        let isoStr = ``iso-8859-1``.GetString(isoBytes)
        isoStr
                
        //let resultBytes = System.Text.Encoding.Convert(``Unicode``,``iso-8859-1``,unicodeBytes)

        //Bug : While followed by lots of code , the parameterInfo will not work here
        //System.Text.Encoding.GetEncoding("iso-8859-1").GetString(isoStr)

    //Pass the XElement which contain the infomation of what we what and parse it . For instance , I want get temperature info , 
    //so I pass the XElement list which contain information of temp, then I use name to get the name of this node ,use value to get value of temp.
    let scrabResultOfExpected (queryXElementResult : list<XElement>) (name : string) (value : string) =
        let nameOfNode =
            queryXElementResult
                |> fun xElement -> xElement.[0]
                |> fun valueOfElement -> valueOfElement.Element(XName.Get(name)).Value

        let vauleOfNodes =
            queryXElementResult
                |> fun xElement -> xElement.[0]
                |> fun valueOfElement -> valueOfElement.Elements(XName.Get(value))
                |> Seq.toList
                |> List.map (fun item -> item.Value)  

        let result = [nameOfNode] @ vauleOfNodes

        result

    // Used to explicit invoke the open Method to avoid reopen the client .
    member this.OpenClient() =
        client.Open()
    
    //Used to explicit invoke the close Method
    member this.CloseClient() =
        client.Close()

    //Bug: C# can't consume the method which defined in F# with default argument.
    //Bug ? : 268097 Make comments just close to "=" failed
    member this.GetTemperatureInfoAtSpecifyPointByNDFDgen(lat : System.Decimal, lon : System.Decimal , index : int) = //, ?timeSeries : TPmap.ServiceTypes.productType, ?startTime : System.DateTime, ?endTime : System.DateTime, ?weatherParam : TPmap.ServiceTypes.weatherParametersType) =
        try
            //client.Open()        
            m_SetDefaultArg

            let data = client.NDFDgen(lat, lon, m_timeSeries,m_startTime, m_endTime, m_weatherParam) 
        
            data
                |> XDocument.Parse
                |> fun doc -> doc.Save(@"C:\Users\v-shuzhu\Desktop\Output.xml")  
            
            //Parse the temperature data from the returned XML string.                    
            let parsedResult = ParseSpecifyNodeFromXMLString(data,"temperature")

            //Query the XElement of temperature           
            let queryTempValue (condition : string) =
                 query{
                        for xElement in parsedResult do
                        where(xElement.Attribute(XName.Get("type")).Value = condition)
                        //Bug : 262064   [Query][Debug]Can't select whole line code while setting breakpoint in query
                        select xElement
                    } 
                        |> Seq.toList
                        
            // Used to provide different items for customers. Including Max,Min and Hourly temperature info.
            let getValueOfTempXElement (index : int) =
                
                let condition = 
                    match index with
                    | 1 -> "maximum" 
                    | 2 -> "minimum"
                    | 3 -> "hourly"
                    | _ -> "Out of index"

                scrabResultOfExpected (queryTempValue(condition)) "name" "value"
                            
            (getValueOfTempXElement index)
                //|> List.iter( fun x -> printfn "%s" x)            
                
        with
            | excn -> ["Here Error"]

    member this.GetCloudInSkyInfoAtSpecifyPointByNDFDgen(lat : System.Decimal, lon : System.Decimal) =        
        try
            //client.Open()
        
            m_SetDefaultArg
        
            let data = client.NDFDgen(lat, lon, m_timeSeries,m_startTime, m_endTime, m_weatherParam)
            
            data
                |> XDocument.Parse
                |> fun doc -> doc.Save(@"C:\Users\v-shuzhu\Desktop\Output.xml")  
                           
            let parsedResult = ParseSpecifyNodeFromXMLString(data,"cloud-amount")          
            let queryResult = 
                query{
                    for xElement in parsedResult do
                    select xElement
                }
                    |> Seq.toList

            (scrabResultOfExpected queryResult "name" "value") 
                               
        with
            | extn -> ["Error"]

    //Not implemented yet
    member this.GetSupportedCityNames() =
        try
            let requestStr = 
                "<soapenv:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
                   xmlns:xsd='http://www.w3.org/2001/XMLSchema' 
                   xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' 
                   xmlns:ndf='http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl'
                   xmlns:dwml='http://www.weather.gov/forecasts/xml/DWMLgen/schema/DWML.xsd'>
                   <soapenv:Header/>
                   <soapenv:Body>
                      <ndf:LatLonListCityNames 
                         soapenv:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
                         <displayLevel xsi:type='dwml:displayLevelType'>1</displayLevel>
                      </ndf:LatLonListCityNames>
                   </soapenv:Body>
                </soapenv:Envelope>
            "
        
            //client.Open()                        
            //client.DisplayInitializationUI()
            try  
                // ??? Can not get the XML string...         
                // Bug here : ParameterInfo doesn't work here.                 
                let result = client.LatLonListCityNames(convertStrToIso(requestStr))
                
                result
                    |> XDocument.Parse
                    |> fun doc -> doc.Save(@"C:\Users\v-shuzhu\Desktop\Output.xml")  
           
            with
                | _ -> printfn "Null"
        
        with
            | excn -> printfn "Get Nothing"

    //For instance : we can get those cities which fit for trival.
    member this.QueryCitiesWithSpecifiedTemp( condition : string, wholeCitiesDicList : list<System.Collections.DictionaryEntry>) =
        
        let roundTemp = [ [90;113]; [64;90]; [32;64]; [0;32] ]
        let tempKey = [ "hot"; "comfortable"; "cold"; "frozen" ]
        let initConditionDicList = ref []
                
        for i in 0..3 do
            initConditionDicList := (!initConditionDicList @ [new System.Collections.DictionaryEntry(tempKey.[i],roundTemp.[i])])            
        
        let tempCondition =
            query{
                for temp in !initConditionDicList do
                where ((temp.Key :?> string) = condition)
                select temp.Value
            } 
                |> Seq.toList
                |> fun x -> x.[0]

        let tempCondition = tempCondition :?> list<int>

        let getWholeCitiesTempDicList =
            let resultList = ref []
           
            for i in wholeCitiesDicList do
                let value = (i.Value) :?> (Decimal * Decimal)
                let maxTemp = (int)(this.GetTemperatureInfoAtSpecifyPointByNDFDgen( (fst value), (snd value), 1 ).[0])
                let minTemp = (int)(this.GetTemperatureInfoAtSpecifyPointByNDFDgen( (fst value), (snd value), 2 ).[0])                
                if(minTemp > (tempCondition.[0]) && (maxTemp < tempCondition.[1])) then
                    resultList := !resultList @ [new System.Collections.DictionaryEntry(i.Key,(minTemp,maxTemp))]
            !resultList            
        
        getWholeCitiesTempDicList        
        
    
    member this.GetIconLink(lat, lon) =
        try
            //client.Open()        
            m_SetDefaultArg       
            let data = client.NDFDgen(lat, lon, m_timeSeries,m_startTime, m_endTime, m_weatherParam)                
            data
                |> XDocument.Parse
                |> fun doc -> doc.Save(@"C:\Users\v-shuzhu\Desktop\Output.xml")                                       
            let parsedResult = ParseSpecifyNodeFromXMLString(data,"conditions-icon") 
                      
            scrabResultOfExpected parsedResult "name" "icon-link" //|> List.iter (fun x -> printfn "%s" x)

         with
            | _ -> ["Icon Error"] 
            
                        
let test = new GetWeather()
test.OpenClient()
test.GetCloudInSkyInfoAtSpecifyPointByNDFDgen(39.0000M,-77.0000M) |> List.iter (fun x -> printfn "%s" x)
////let time = new System.Timers.Timer(20000.0)
////time.Start()
test.GetTemperatureInfoAtSpecifyPointByNDFDgen(39.0000M,-77.0000M, 3)  |> List.iter (fun x -> printfn "%s" x)
test.GetSupportedCityNames() //|> printfn "%s"
//test.GetIconLink(39.0000M,-77.0000M)
test.GetIconLink(39.0000M,-77.0000M) |> List.iter (fun x -> printfn "%s" x)

test.CloseClient()

 这个还不够完善,不过还是要做个笔记比较好~ :)

posted @ 2012-11-12 12:27  ZackZhou  阅读(414)  评论(0编辑  收藏  举报