Skip to content

Instantly share code, notes, and snippets.

@ndbroadbent
Last active August 29, 2015 14:05
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 ndbroadbent/0d31b36d57c777f4713e to your computer and use it in GitHub Desktop.
Save ndbroadbent/0d31b36d57c777f4713e to your computer and use it in GitHub Desktop.
QR Code standard for food products
# Ruby code to parse a food product QR Code
class FoodQRParser
class << self
def parse(qr_string)
data = {}
sections = qr_string.split(';')
data[:upc] = sections[0]
data[:expiration_date] = sections[1].to_date
data[:servings] = sections[2].to_i if sections[2]
if nutritional_data = sections[3]
data[:nutritional_information] = parse_nutritional_data(nutritional_data)
end
sections[4..-1].each do |remaining_section|
section_type, section_data = remaining_section.split(':')
case section_type.to_sym
when :m
data[:cooking_instructions] ||= {}
data[:cooking_instructions][:microwave] = parse_microwave_instructions(section_data)
else
raise "Unrecognized section type (#{section_type})!"
end
end
data
end
private
NUTRITIONAL_DATA_FIELDS = %w(calories protein total_fat saturated_fat carbohydrates fiber sugars sodium).map(&:to_sym).freeze
def parse_nutritional_data(nutrition_string)
nutrition_values = nutrition_string.split(',').map {|s| s == "" ? nil : s.to_i }
field_value_pairs = NUTRITIONAL_DATA_FIELDS.zip(nutrition_values)
Hash[field_value_pairs]
end
COOKING_POWER_LEVELS = %w(high medium low defrost).each_with_object({}) {|l, h| h[l[0].upcase.to_sym] = l }.freeze
def parse_microwave_instructions(cooking_string)
data = {steps: []}
base_power, steps = cooking_string.split(',')
data[:base_power] = base_power.to_i
steps.scan(/[LMHW]\d+|S/).each do |step|
step_type, step_data = step[0].to_sym, step[1..-1]
case step_type
when :H, :M, :L
power_level = COOKING_POWER_LEVELS[step_type]
data[:steps] << { step: "cook", power: power_level, time: step_data.to_i }
when :W
data[:steps] << { step: "wait", time: step_data.to_i }
when :S
data[:steps] << { step: "stir" }
else
raise "Unrecognized step type! (#{step_type})!"
end
end
data
end
end
end
FoodQRParser.parse("0013800103420;20140828;2;340,15,16,7,33,,2,820;m:700,H480SH180W60")
#=> {
# :upc => "0013800103420",
# :expiration_date => Thu, 28 Aug 2014,
# :servings => 2,
# :nutritional_information => {
# :calories => 340,
# :protein => 15,
# :total_fat => 16,
# :saturated_fat => 7,
# :carbohydrates => 33,
# :fiber => nil,
# :sugars => 2,
# :sodium => 820
# },
# :cooking_instructions => {
# :microwave => {
# :steps => [
# [0] {
# :step => "cook",
# :power => "high",
# :time => 480
# },
# [1] {
# :step => "stir"
# },
# [2] {
# :step => "cook",
# :power => "high",
# :time => 180
# },
# [3] {
# :step => "wait",
# :time => 60
# }
# ],
# :base_power => 700
# }
# }
# }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment