Skip to content

Instantly share code, notes, and snippets.

@exlee
Created November 20, 2017 13:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save exlee/4748738ad126fd36d3c96d62333d607d to your computer and use it in GitHub Desktop.
Save exlee/4748738ad126fd36d3c96d62333d607d to your computer and use it in GitHub Desktop.
# Declarative File Parser written in Elixir
require Poison.Parser
defmodule Flatten do
def transpose([[]|_]), do: []
def transpose(a) do
[Enum.map(a, &hd/1) | transpose(Enum.map(a, &tl/1))]
end
def parse_file(data) do
lines = Enum.map(data["m_LStudentData"], &student_map(&1))
[first_student | _] = data["m_LStudentData"] |> Enum.to_list
table = [headers(first_student) | lines]
#IO.puts "sep=," # Excel
table
|> transpose
|> Enum.map(&Enum.join(&1, ";"))
end
def headers(student) do
["Student name"] ++ student_hmap(student) |> List.flatten
end
def student_map(student) do
chapters = Enum.map(student["m_LChapReport"], &chapter_map(&1))
[student["m_StudentProfileName"] | List.flatten(chapters)]
end
def chapter_map(chapter) do
chapter["m_ChapterName"]
actions = Enum.map(chapter["m_LReportAct"], &action_map(&1))
actions
end
def action_map(action) do
[
action["m_PctProgression"],
action["m_TimeSpent"],
action["m_ErrorPerStep"] |> Enum.join(":")
]
end
def student_hmap(student) do
student["m_LChapReport"]
|> Enum.map(&chapter_hmap/1)
end
def chapter_hmap(chapter) do
Enum.map(chapter["m_LReportAct"], &action_hmap(chapter["m_ChapterName"], &1))
end
def action_hmap(chapter_name, action) do
action_name = action["m_Name"]
action_config = action["m_Config"]
~w(Progression TimeSpent ErrorsPerStep)
|> Enum.map(fn type -> Enum.join([chapter_name, action_name, action_config, type], "::") end)
end
def process([id, create_date, data]) do
case Poison.Parser.parse(data) do
{:ok, data} ->
teacher = data["m_TeacherProfileName"]
IO.puts "#{id}:#{create_date}:#{teacher}"
try do
data = Flatten.parse_file(data)
|> Enum.join("\n")
File.write!("#{id}.csv", data)
rescue
e -> IO.puts "Cannot be parsed"
end
{:error, _} ->
IO.puts "Cannot be parsed"
end
end
end
{:ok, pid} = Postgrex.start_link(database: "DATABASE", username: "USERNAME", password: "PASSWORD", hostname: "HOST", sync_connect: true, port: 5452, ssl: true)
{:ok, result} = Postgrex.query(pid, "SELECT * FROM edu_report", [])
Enum.each(result.rows, &Flatten.process/1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment