Weather lookup service

Discussion in 'ComputerCraft Programming' started by sk89q, 8 January 2013.

  1. sk89q

    sk89q Administrator
    Staff Member

    Joined:
    1 December 2011
    Messages:
    2.490
    Likes Received:
    1.504
    As a first script to test out ComputerCraft, this looks up weather for any place on Earth.

    2013-01-07_22.15.43.jpg 2013-01-07_22.16.14.jpg 2013-01-07_22.16.jpg

    Note: I stole trim(), escape(), and wrap() from the Lua wiki.

    Code:
    function trim(s)
      return s:match"^%s*(.*)":match"(.-)%s*$"
    end
     
    function escape(str)
      if str then
        str = string.gsub(str, "\n", "\r\n")
        str = string.gsub(str, "([^%w ])", function(c) return string.format("%%%02X", string.byte(c)) end)
        str = string.gsub(str, " ", "+")
      end
     
      return str
    end
     
    function wrap(str, limit)
      local here = 1
      return str:gsub("(%s+)()(%S+)()",
        function(sp, st, word, fi)
          if fi - here > limit then
            here = st
            return "\n" .. word
          end
      end)
    end
     
    function getWoeid(loc)
      local query = "SELECT * FROM geo.places WHERE text = \"" .. escape(loc) .. "\""
      local f = http.get("http://query.yahooapis.com/v1/public/yql?q=" .. escape(query) .. "&format=xml")
      local data = f.readAll()
      local woeid = string.match(data, "<woeid>([0-9]+)</woeid>")
      local name = string.match(data, "<name>([^<]+)</name>")
      f.close()
      return woeid, name
    end
     
    function getWeather(woeid)
      local f = http.get("http://weather.yahooapis.com/forecastrss?w=" .. woeid)
      local data = f.readAll()
      local current = string.match(data, "Current Conditions:</b><br />([^<]+)<BR />")
      local forecast = string.match(data, "Forecast:</b><BR />([^<]+)<br />")
      f.close()
      return trim(current), trim(forecast)
    end
     
    function printSys(message)
      term.setBackgroundColor(colors.red)
      term.setTextColor(colors.white)
      print(message)
      term.setBackgroundColor(colors.black)
    end
     
    function printErr(message)
      term.setTextColor(colors.red)
      print(message)
      term.setTextColor(colors.white)
    end
     
    function printStatus(message)
      term.setTextColor(colors.yellow)
      print(message)
      term.setTextColor(colors.white)
    end
     
    function printText(pr, title, text)
      pr.newPage()
      pr.setPageTitle(title)
     
      local w, h = pr.getPageSize()
      local lineNo = 1
      for token in string.gmatch(text, "[^\n]+") do
        for line in string.gmatch(wrap(token, w), "[^\n]+") do
          -- may need new page!
          if lineNo > h then
            lineNo = 1
            if not pr.endPage() then
              return false
            end
            pr.newPage()
            pr.setPageTitle(title)
            w, h = pr.getPageSize()
          end
     
          pr.setCursorPos(1, lineNo)
          pr.write(line)
          lineNo = lineNo + 1
        end
      end
     
      return pr.endPage()
    end
     
    local pr = peripheral.wrap("right")
    local run = true
     
    while run do
      -- reset
      term.clear()
      term.setCursorPos(1, 1)
      redstone.setOutput("back", false)
     
      printSys("WEATHER LOOKUP SERVICE")
      print("\nLookup the weather of any location on Earth! Enter the name of the place below.\n")
      write("Enter location: ")
     
      local loc = read()
     
      if loc ~= "quit" then
        local woeid, name = getWoeid(loc)
     
        if woeid then
          term.clear()
          term.setCursorPos(1, 1)
     
          local current, forecast = getWeather(woeid)
          printStatus("Weather for " .. name)
          print("Current: " .. current)
          print("Forecast: " .. forecast)
     
          print("")
          printStatus("Would you like a printout? [Y/N]")
          local reply = trim(read())
          if reply == "y" or reply == "Y" then
            local title = "Weather Report for " .. name
            local text = "Weather for " .. name .. "\n\nCurrent: " .. current .. "\nForecast: " .. forecast
            local ret = printText(pr, title, text)
     
            if ret then
              printStatus("Printed. Please wait a second...")
              redstone.setOutput("back", true)
              sleep(1)
              redstone.setOutput("back", false)
            else
              printErr("No ink/paper in the printer!")
            end
          end
        else
          printErr("Sorry, that location can't be found!")
        end
      else
        run = false
      end
    end
     
    Ali and thtredstonegui like this.
  2. Ali

    Ali SupaHam

    Joined:
    7 February 2012
    Messages:
    139
    Likes Received:
    43
    I bet you can't code WorldEdit now! >: D
     
  3. DSoS

    DSoS Member

    Joined:
    6 December 2012
    Messages:
    128
    Likes Received:
    18
    so if I'm understanding this correctly I can use MineCraft to check the weather in my city?

    That is freaking awesome :D

    Yet, just another thing to make us even more lazy XD

    Edited out a line and added a line.
     
  4. Chaeris

    Chaeris Active Member

    Joined:
    8 March 2012
    Messages:
    766
    Likes Received:
    89
    now, what about a webpage reader ?
    No jsut joking, it would mean an HTML reader :D
     
  5. Ali

    Ali SupaHam

    Joined:
    7 February 2012
    Messages:
    139
    Likes Received:
    43
    It has been done before on the web.
     
  6. Chaeris

    Chaeris Active Member

    Joined:
    8 March 2012
    Messages:
    766
    Likes Received:
    89
    You know what ?
    I though the spoiler in your message was the code...
    So disappointed!
     
  7. Ali

    Ali SupaHam

    Joined:
    7 February 2012
    Messages:
    139
    Likes Received:
    43
    *facepalm* it is my signature, and time to change it, its getting boring now.
     
  8. Chaeris

    Chaeris Active Member

    Joined:
    8 March 2012
    Messages:
    766
    Likes Received:
    89
    Please, in your new signature, remove your spoiler, it's annoying sometimes ;)
     
  9. Ali

    Ali SupaHam

    Joined:
    7 February 2012
    Messages:
    139
    Likes Received:
    43
    No I would not rather have a couple of posts in one page and fill the whole page twice as big because my picture is too big.
     
    DarkMaterias likes this.
  10. Chaeris

    Chaeris Active Member

    Joined:
    8 March 2012
    Messages:
    766
    Likes Received:
    89
    Then choose (as me) a little pic, and maybe some words ?
     
  11. Ali

    Ali SupaHam

    Joined:
    7 February 2012
    Messages:
    139
    Likes Received:
    43
    And why not just have a spoiler that has a bigger picture? I won't change it so no need to try talk me to it, unless it is against the rules there is no need for me to change it!
     
  12. Chaeris

    Chaeris Active Member

    Joined:
    8 March 2012
    Messages:
    766
    Likes Received:
    89
    Ok, do what you want, remember it was just a suggestion, so I won't force you.