<commit_before>require "moonshine"
require "redis"
require "html/builder"

include Moonshine
include Moonshine::Shortcuts
include Moonshine::Http

# Compose Objects (like Hash) to have a to_json method
require "json/to_json"

REDIS = Redis.new
app = Moonshine::App.new

class CONTENT
  UTF8 = "; charset=UTF-8"
  JSON = "application/json" + UTF8
  PLAIN = "text/plain"
  HTML = "text/html" + UTF8
end


app.response_middleware do |req, res|
    res.headers["Server"] = "Moonshine"
    res.headers["Date"] = Time.now.to_s
    res
end

private def randomWorld
  id = rand(1...10_000)
  {
    :id => id
    :randomNumber => REDIS.get("world:" + id.to_s)
  }
end

app.define do

  # Test 1: JSON Serialization
  get "/json", do |request|
    res = ok({ :message => "Hello, World!" }.to_json)
    res.headers["Content-type"] = CONTENT::JSON
    res
  end

  # Test 2: Single database query
  route "/db", do |request|
    res = ok(randomWorld.to_json)
    res.headers["Content-type"] = CONTENT::JSON
    res
  end

  # Test 3: Multiple database query
  route "/queries", do |request|
    queries = request.get["queries"].to_i
    queries = 1 if queries < 1
    queries = 500 if queries > 500

    results = (1..queries).map do
      randomWorld
    end

    res = ok(results.to_json)
    res.headers["Content-type"] = CONTENT::JSON
    res
  end

  # Test 4: Fortunes
  route "/fortunes", do |request|
    data = [] of  Hash(Symbol, (String | Int32))

    REDIS.lrange("fortunes", 0, -1).each_with_index do |e, i|
      data.push({ :id => i + 1, :message => e.to_s })
    end
    
    additional_fortune = {
      :id => 0
      :message => "Additional fortune added at request time."
    }
    data.push(additional_fortune)

    data.sort! { |a, b|
      a[:message].to_s <=> b[:message].to_s
    }

    # New builder for each request!
    html = HTML::Builder.new.build do
      html {
        head {
          title { text "Fortunes" }
        }
        body {
          table {
            tr {
              thead { text "id" }
              thead { text "message" }
            }
            data.each { |e|
              tr {
                td { text e[:id].to_s }
                td { text e[:message].to_s }
              }
            }
          }
        }
      }
    end

    # Doctype not available in builder
    # builder only supports `thead`, tests need to see `th`
    res = ok("<!doctype html>" + html.gsub("thead", "th"))
    res.headers["Content-type"] = CONTENT::HTML
    res
  end

  # Test 6: Plaintext
  route "/plaintext", do |request|
    res = ok("Hello, World!")
    res.headers["Content-type"] = CONTENT::PLAIN<commit_msg>All redis tests passing<commit_after>require "moonshine"
require "redis"
require "html/builder"

include Moonshine
include Moonshine::Shortcuts
include Moonshine::Http

# Compose Objects (like Hash) to have a to_json method
require "json/to_json"

REDIS = Redis.new
app = Moonshine::App.new

class CONTENT
  UTF8 = "; charset=UTF-8"
  JSON = "application/json" + UTF8
  PLAIN = "text/plain"
  HTML = "text/html" + UTF8
end

ID_MAXIMUM = 10_000

app.response_middleware do |req, res|
    res.headers["Server"] = "Moonshine"
    res.headers["Date"] = Time.now.to_s
    res
end

private def randomWorld
  id = rand(1..ID_MAXIMUM)
  num = REDIS.get("world:" + id.to_s)
  puts num
  {
    :id => id
    :randomNumber => num
  }
end

private def setWorld(world)
  id = "world:" + world[:id].to_s
  REDIS.set(id, world[:randomNumber])
  world
end

private def sanitizedQueryCount(request)
  begin
    queries = request.get["queries"].to_i
  rescue
    queries = 1
  end
  queries = 1 if queries < 1
  queries = 500 if queries > 500
  queries
end

app.define do

  # Test 1: JSON Serialization
  get "/json", do |request|
    res = ok({ :message => "Hello, World!" }.to_json)
    res.headers["Content-type"] = CONTENT::JSON
    res
  end

  # Test 2: Single database query
  route "/db", do |request|
    res = ok(randomWorld.to_json)
    res.headers["Content-type"] = CONTENT::JSON
    res
  end

  # Test 3: Multiple database query
  route "/queries", do |request|
    results = (1..sanitizedQueryCount(request)).map do
      randomWorld
    end

    res = ok(results.to_json)
    res.headers["Content-type"] = CONTENT::JSON
    res
  end

  # Test 4: Fortunes
  route "/fortunes", do |request|
    data = [] of  Hash(Symbol, (String | Int32))

    REDIS.lrange("fortunes", 0, -1).each_with_index do |e, i|
      data.push({ :id => i + 1, :message => e.to_s })
    end
    
    additional_fortune = {
      :id => 0
      :message => "Additional fortune added at request time."
    }
    data.push(additional_fortune)

    data.sort! { |a, b|
      a[:message].to_s <=> b[:message].to_s
    }

    # New builder for each request!
    html = HTML::Builder.new.build do
      html {
        head {
          title { text "Fortunes" }
        }
        body {
          table {
            tr {
              thead { text "id" }
              thead { text "message" }
            }
            data.each { |e|
              tr {
                td { text e[:id].to_s }
                td { text e[:message].to_s }
              }
            }
          }
        }
      }
    end

    # Doctype not available in builder
    # builder only supports `thead`, tests need to see `th`
    res = ok("<!doctype html>" + html.gsub("thead", "th"))
    res.headers["Content-type"] = CONTENT::HTML
    res
  end

  # Test 5: Database Updates
  route "/updates", do |request|
    updated = (1..sanitizedQueryCount(request)).map do
      world = randomWorld
      world[:randomNumber] = rand(1..ID_MAXIMUM)
      setWorld(world)
    end

    res = ok(updated.to_json)
    res.headers["Content-type"] = CONTENT::JSON
    res
  end

  # Test 6: Plaintext
  route "/plaintext", do |request|
    res = ok("Hello, World!")
    res.headers["Content-type"] = CONTENT::PLAIN
{'fraction_non_alphanumeric': 0.13263229308005428, 'fraction_numerical': 0.010854816824966078, 'mean_word_length': 2.2706600110926236, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4724417', 'n_tokens_mistral': 2087, 'n_tokens_neox': 1998, 'n_words': 523}