How works drag and drop quizz? - openedx

The GUI gives very hard to get sample code. Especially :
correct_answer = {
'1': [[100, 150], 100],
'2': [[300, 150], 100],
'3': [[500, 150], 100],
'4': [[700, 150], 100]}
How to understand and use it ?

It's documented there.
The hard part it the 'id': [[x coordinate, y coordinate], radius].
<problem>
Recreate the sentence : `Demain, je vais marche`.
<customresponse>
<drag_and_drop_input img="https://studio.edx.org/c4x/edX/DemoX/asset/L9_buckets.png">
<draggable id="1" label="I"/>
<draggable id="3" label="walk"/>
<draggable id="4" label="tomorrow"/>
<draggable id="2" label="will"/>
</drag_and_drop_input>
<answer type="loncapa/python">
correct_answer = {
'1': [[100, 150], 100],
'2': [[300, 150], 100],
'3': [[500, 150], 100],
'4': [[700, 150], 100]}
if draganddrop.grade(submission[0], correct_answer):
correct = ['correct']
else:
correct = ['incorrect']
</answer>
</customresponse>
</problem>

Related

Rails 5 - Attribute update if relative model's attribute is different

I've created an attribute that is supposed to update a datetime field with the value of a child model's attribute if it's newer (or older based on which field)
def update_project_record
client = Client.find(project.client_id)
puts client
project.start_date = self.task_start_date if self.task_start_date < project.start_date
project.end_date = self.task_end_date if self.task_end_date > project.end_date
if client.nearest_project_start.present?
client.assign_attributes(:nearest_project_start => self.task_start_date, :nearest_project_id => self.project_id) if self.task_start_date < client.nearest_project_start
else
client.assign_attributes(:nearest_project_start => self.task_start_date, :nearest_project_id => self.project_id)
end
if client.furthest_project_end.present?
client.assign_attributes(:furthest_project_end => self.task_end_date, :furthest_project_id => self.project_id) if self.task_end_date > client.furthest_project_end
else
client.assign_attributes(:furthest_project_end => self.task_end_date, :furthest_project_id => self.project_id)
end
client.save
end
It's messy, but it is working within the app.
A Client has many Projects which has many Tasks and a Client has many Tasks through Projects
However, when I try to seed the DB I am seeing an output similar to:
SDK Enhancement
#<Client:0x007fa89d33bda8>
#<Client:0x007fa89d31a108>
Task 1
#<Client:0x007fa89d2c1580>
#<Client:0x007fa89d2a0880>
Task 3
#<Client:0x007fa89d2488b0>
#<Client:0x007fa89d21bae0>
Task 4
#<Client:0x007fa89d1bfbc8>
#<Client:0x007fa89d19eec8>
Task 5
#<Client:0x007fa89d142e98>
#<Client:0x007fa89d11e0c0>
Task 6
#<Client:0x007fa89d0c1f78>
#<Client:0x007fa89d0a1278>
Task 7
#<Client:0x007fa89d049208>
#<Client:0x007fa89d024430>
Task 8
#<Client:0x007fa89cfcc3c0>
#<Client:0x007fa89cfa3588>
Task 9
#<Client:0x007fa89cf4b478>
#<Client:0x007fa89cf2a5c0>
Task 17
#<Client:0x007fa89ced2438>
#<Client:0x007fa89ceb1670>
Task 28
#<Client:0x007fa89ce59600>
#<Client:0x007fa89ce348a0>
Task 39
Which seems like it's pulling the Client but not updating the record? (Unsure how to test this theory).
I then went into the app and make a Client -> Project -> Task as a user would and all records look as if I would expect, but it seems like Seeding ignores this function, but it IS updating the Project portion.
Seed File
task_list = [
['Task 1', 'Nothing to add', '2017-09-01', '2018-01-01', 1, 1, 0],
['Task 3', 'Nothing to add', '2017-08-01', '2017-10-01', 1, 2, 1],
['Task 4', 'Nothing to add', '2017-06-01', '2017-09-01', 1, 3, 1],
['Task 5', 'Nothing to add', '2017-11-01', '2017-12-01', 1, 4, 0],
['Task 6', 'Nothing to add', '2017-08-01', '2018-02-01', 1, 5, 0],
['Task 7', 'Nothing to add', '2017-08-01', '2017-12-01', 1, 6, 0],
['Task 8', 'Nothing to add', '2017-11-01', '2017-12-15', 1, 7, 0],
['Task 9', 'Nothing to add', '2017-07-01', '2017-08-15', 1, 1, 0],
['Task 17', 'Nothing to add', '2017-04-01', '2017-08-01', 1, 6, 1],
['Task 28', 'Nothing to add', '2017-08-01', '2017-10-01', 1, 7, 0],
['Task 39', 'Nothing to add', '2018-01-01', '2018-04-01', 1, 1, 1]
]
task_list.each do |name, comment, start, end_date, project, product, completed|
dproject = Project.find(project)
dproject.tasks.create!(task_name: name, comment: comment, task_start_date: start, task_end_date: end_date, project_id: project, product: product, completed: completed)
puts name
end
I originally didn't have the project assignment line but I was seeing if perhaps that resolved the MIA Client details.
Tl;dr
If a Task is created and has a later end_date than the Client's furthest_project_end datefield, it should update that field. It is not currently updating. It IS however updating the project.end_date

Most efficient way to convert a ruby hash with array as keys to one with single values as keys

I'm stuck on what is the best way to re-arrange my ruby hash.
The main goal is to group results from mysql by month and count.
To do it, i make this request:
#data = Model.find(params[:id])
.jobs
.group('year(created_at)')
.group('month(created_at)')
.count(:id)
Which gives me:
#=> {[2013, 12]=>9, [2014, 1]=>4, [2014, 3]=>3,
# [2014, 4]=>1, [2014, 6]=>1, [2014, 7]=>1, [2014, 10]=>2}
I'm trying to have a cleaner hash or array to convert to json, where the years are not duplicated.
How can I have something workable like {"Year" => [Month,Count value]}? (or other form)
Idea? (I run ruby 2.2)
The answer proposed by #mudosobwa might be correct, but because your target is a json file, you may want some 'named' keys. I suggest you this one :
formated_results = #data.group_by{|k, v| k[0]}.collect{|k,v| {year: k, datas: v.collect{|vv| {month: vv.first.last, count: vv.last}}}}
# {:year=>2013, :datas=>[{:month=>12, :count=>9}]}
# {:year=>2014, :datas=>[{:month=>1, :count=>4}, {:month=>3, :count=>3}, {:month=>4, :count=>1}, {:month=>6, :count=>1}, {:month=>7, :count=>1}, {:month=>10, :count=>2}]}
EDIT : An other solution without the group_by method :
formated_results = Hash.new{|h,k| h[k] = []}
#data.each{|k,v| formated_results[k[0]] << {month: k[1], count: v}}
formated_results = formated_results.collect{|k, v| {year: k, datas: v}}
# {:year=>2013, :datas=>[{:month=>12, :count=>9}]}
# {:year=>2014, :datas=>[{:month=>1, :count=>4}, {:month=>3, :count=>3}, {:month=>4, :count=>1}, {:month=>6, :count=>1}, {:month=>7, :count=>1}, {:month=>10, :count=>2}]}
Then you just have to
formated_results.to_json
The json result shall be :
[
{
"year": 2013,
"datas": [
{ "month": 12, "count": 9 }
]
},
{
"year": 2014,
"datas": [
{ "month": 1, "count": 4 },
{ "month": 3, "count": 3 },
{ "month": 4, "count": 1 },
{ "month": 6, "count": 1 },
{ "month": 7, "count": 1 },
{ "month": 10, "count": 2 }
]
}
]
Given you already have your hash in #data, you might:
#data.inject({}) do |memo, ((y, m), cnt)|
(memo[y] ||= {})[m] = cnt
memo
end
#⇒ {
# 2013 => {12 => 9},
# 2014 => {1 => 4, 10 => 2, 3 => 3, 4 => 1, 6 => 1, 7 => 1}
# }
As it was noted by #Surya in comments, it should be hash Year => Hash[Month, Count]. While you still want to have arrays of Month, Count:
#data.inject({}) do |memo, ((y, m), cnt)|
memo[y] ||= []
memo[y] << [m, cnt]
memo
end
To json:
require 'json'
result.to_json
#=> "{\"2013\":{\"12\":9},\"2014\":{\"1\":4,\"3\":3,\"4\":1,\"6\":1,\"7\":1,\"10\":2}}"
#data.to_a.group_by{|ym, c| ym.first }.map{|year, months| [year,months.map{|m,cnt| [m.last, cnt] }] }.to_h
=> {2013=>[[12, 9]], 2014=>[[1, 4], [3, 3], [4, 1], [6, 1], [7, 1], [10, 2]]}

Checking for Valid UK PostCode

I have some code which is written in mysql (i think) to return valid postcodes, and I am trying to convert the code to Firebird SQL but I am getting errors. Stopping at the CASE part at the minute. What I want to happen eventually is for it to delete all non-valid postcodes. So if you know an another solution that would be of great help:
SET TERM ^ ;
CREATE PROCEDURE ValidatePostCode ( PostCode VARCHAR(8) )
RETURNS ( ValidPC CHAR(1) )
AS
BEGIN
RETURN CASE
-- Special case GIR 0AA
WHEN PostCode LIKE 'GIR 0AA' THEN i=1
-- Current postcode prefixes
WHEN LEFT(Postcode, 2) NOT IN ('AB', 'AL', 'BA', 'BB', 'BD', 'BH', 'BL', 'BN', 'BR', 'BS', 'BT', 'CA', 'CB', 'CF', 'CH', 'CM', 'CO', 'CR', 'CT', 'CV', 'CW', 'DA', 'DD', 'DE', 'DG', 'DH', 'DL', 'DN', 'DT', 'DY', 'EC', 'EH', 'EN', 'EX', 'FK', 'FY', 'GL', 'GU', 'GY', 'HA', 'HD', 'HG', 'HP', 'HR', 'HS', 'HU', 'HX', 'IG', 'IM', 'IP', 'IV', 'JE', 'KA', 'KT', 'KW', 'KY', 'L', 'LA', 'LD', 'LE', 'LL', 'LN', 'LS', 'LU', 'ME', 'MK', 'ML', 'NE', 'NG', 'NN', 'NP', 'NR', 'NW', 'OL', 'OX', 'PA', 'PE', 'PH', 'PL', 'PO', 'PR', 'RG', 'RH', 'RM', 'SA', 'SE', 'SG', 'SK', 'SL', 'SM', 'SN', 'SO', 'SP', 'SR', 'SS', 'ST', 'SW', 'SY', 'TA', 'TD', 'TF', 'TN', 'TQ', 'TR', 'TS', 'TW', 'UB', 'WA', 'WC', 'WD', 'WF', 'WN', 'WR', 'WS', 'WV', 'YO', 'ZE')
OR WHEN LEFT(Postcode, 1) NOT IN ('B', 'E', 'G', 'L', 'N', 'S', 'W') THEN 0
-- AANN NAA
WHEN PostCode LIKE '[ABCDEFGHIJKLMNOPRSTUWYZ][ABCDEFGHKLMNOPQRSTUVWXY][0123456789][0123456789] [0123456789][ABDEFGHJLNPQRSTUWXYZ][ABDEFGHJLNPQRSTUWXYZ]' THEN 1
-- AANA NAA
WHEN PostCode LIKE '[ABCDEFGHIJKLMNOPRSTUWYZ][ABCDEFGHKLMNOPQRSTUVWXY][0123456789][ABEHMNPRVWXY] [0123456789][ABDEFGHJLNPQRSTUWXYZ][ABDEFGHJLNPQRSTUWXYZ]' THEN 1
-- ANN NAA
WHEN PostCode LIKE '[ABCDEFGHIJKLMNOPRSTUWYZ][0123456789][0123456789] [0123456789][ABDEFGHJLNPQRSTUWXYZ][ABDEFGHJLNPQRSTUWXYZ]' THEN 1
-- AAN NAA
WHEN PostCode LIKE '[ABCDEFGHIJKLMNOPRSTUWYZ][ABCDEFGHKLMNOPQRSTUVWXY][0123456789] [0123456789][ABDEFGHJLNPQRSTUWXYZ][ABDEFGHJLNPQRSTUWXYZ]' THEN 1
-- ANA NAA
WHEN PostCode LIKE '[ABCDEFGHIJKLMNOPRSTUWYZ][0123456789][ABCDEFGHJKSTUW] [0123456789][ABDEFGHJLNPQRSTUWXYZ][ABDEFGHJLNPQRSTUWXYZ]' THEN 1
-- AN NAA
WHEN PostCode LIKE '[ABCDEFGHIJKLMNOPRSTUWYZ][0123456789] [0123456789][ABDEFGHJLNPQRSTUWXYZ][ABDEFGHJLNPQRSTUWXYZ]' THEN 1
-- Not a valid postcode
ELSE 0
END
END^
SET TERM ; ^
I ended up doing the following thanks to useful comment:
select postcode from CUSTOMER_ADDRESSES
where LEFT(postcode, 2) NOT IN ('AB', 'AL', 'BA', 'BB', 'BD', 'BH', 'BL', 'BN', 'BR', 'BS', 'BT', 'CA', 'CB', 'CF', 'CH', 'CM', 'CO', 'CR', 'CT', 'CV', 'CW', 'DA', 'DD', 'DE', 'DG', 'DH', 'DL', 'DN', 'DT', 'DY', 'EC', 'EH', 'EN', 'EX', 'FK', 'FY', 'GL', 'GU', 'GY', 'HA', 'HD', 'HG', 'HP', 'HR', 'HS', 'HU', 'HX', 'IG', 'IM', 'IP', 'IV', 'JE', 'KA', 'KT', 'KW', 'KY', 'L', 'LA', 'LD', 'LE', 'LL', 'LN', 'LS', 'LU', 'ME', 'MK', 'ML', 'NE', 'NG', 'NN', 'NP', 'NR', 'NW', 'OL', 'OX', 'PA', 'PE', 'PH', 'PL', 'PO', 'PR', 'RG', 'RH', 'RM', 'SA', 'SE', 'SG', 'SK', 'SL', 'SM', 'SN', 'SO', 'SP', 'SR', 'SS', 'ST', 'SW', 'SY', 'TA', 'TD', 'TF', 'TN', 'TQ', 'TR', 'TS', 'TW', 'UB', 'WA', 'WC', 'WD', 'WF', 'WN', 'WR', 'WS', 'WV', 'YO', 'ZE') OR LEFT(postcode, 1) NOT IN ('B', 'E', 'G', 'L', 'N', 'S', 'W')
and postcode not SIMILAR TO '[ABCDEFGHIJKLMNOPRSTUWYZ][ABCDEFGHKLMNOPQRSTUVWXY][0123456789][0123456789][0123456789][ABDEFGHJLNPQRSTUWXYZ][ABDEFGHJLNPQRSTUWXYZ]'
and postcode not SIMILAR TO '[ABCDEFGHIJKLMNOPRSTUWYZ][ABCDEFGHKLMNOPQRSTUVWXY][0123456789][ABEHMNPRVWXY][0123456789][ABDEFGHJLNPQRSTUWXYZ][ABDEFGHJLNPQRSTUWXYZ]'
and postcode not SIMILAR TO '[ABCDEFGHIJKLMNOPRSTUWYZ][0123456789][0123456789][0123456789][ABDEFGHJLNPQRSTUWXYZ][ABDEFGHJLNPQRSTUWXYZ]'
and postcode not SIMILAR TO '[ABCDEFGHIJKLMNOPRSTUWYZ][ABCDEFGHKLMNOPQRSTUVWXY][0123456789][0123456789][ABDEFGHJLNPQRSTUWXYZ][ABDEFGHJLNPQRSTUWXYZ]'
and postcode not SIMILAR TO '[ABCDEFGHIJKLMNOPRSTUWYZ][0123456789][ABCDEFGHJKSTUW][0123456789][ABDEFGHJLNPQRSTUWXYZ][ABDEFGHJLNPQRSTUWXYZ]'
and postcode not SIMILAR TO '[ABCDEFGHIJKLMNOPRSTUWYZ][0123456789][0123456789][ABDEFGHJLNPQRSTUWXYZ][ABDEFGHJLNPQRSTUWXYZ]'
Before doing this however I removed all the spaces as they were not needed. If they were needed I would have put a space in the similar to string. Here is the code I used to remove the spaces:
update CUSTOMER_ADDRESSES set POSTCODE = replace(POSTCODE, ' ', '');

Dictionary-based NLTK tagger

I want to tag location string in text using NLTK and also in Stanford-NLP
and am looking for dictionary lookup tagger for NLTK/Stanford-NLP, for so far I haven't found anything with Dictionary-lookup method.
One way is to use RegexpTagger(NLTK) and supply every location strings in there, but it might slow.
I don't need to do any semantic analysis, other than to tag the locations based on my location-dictionary.
Ideas ?
You could use UnigramTagger:
#!/usr/bin/env python2
from nltk.tag.sequential import UnigramTagger
from nltk.tokenize import word_tokenize, sent_tokenize
text = 'I visited Paris and Bordeaux. Not Los Angeles'
locations = [[('Paris', 'LOC'), ('Bordeaux', 'LOC'), ('France', 'LOC'),
('Los Angeles', 'LOC')]]
location_tagger = UnigramTagger(locations)
for sentence in sent_tokenize(text):
tokens = word_tokenize(sentence)
print(location_tagger.tag(tokens))
Prints:
[('I', None), ('visited', None), ('Paris', 'LOC'), ('and', None),
('Bordeaux', 'LOC'), (',', None), ('but', None), ('not', None),
('Los', None), ('Angeles', None)]
You will need a better tokenizer if you want to tag multi-word locations like Los Angeles.
If all you need is to look up from dictionaries, then htql.RegEx() may be a good fit. Here is the example from http://htql.net:
import htql;
address = '88-21 64th st , Rego Park , New York 11374'
states=['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut',
'Delaware', 'District Of Columbia', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana',
'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan',
'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire',
'New Jersey', 'New Mexico', 'New York', 'North Carolina', 'North Dakota', 'Ohio', 'Oklahoma',
'Oregon', 'PALAU', 'Pennsylvania', 'PUERTO RICO', 'Rhode Island', 'South Carolina', 'South Dakota',
'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin',
'Wyoming'];
a=htql.RegEx();
a.setNameSet('states', states);
state_zip1=a.reSearchStr(address, "&[s:states][,\s]+\d{5}", case=False)[0];
# state_zip1 = 'New York 11374'
state_zip2=a.reSearchList(address.split(), r"&[ws:states]<,>?<\d{5}>", case=False)[0];
# state_zip2 = ['New', 'York', '11374']
You can use parameter: useindex=True to return matching positions.

Put data in specific header

headers = ["05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22"]
data = ["05:01", "05:23", "05:43", "06:03", "06:33", "06:53", "07:03", "07:23", "07:46", "08:04", "08:24", "08:44", "09:14", "09:24", "09:44", "10:19", "10:39", "11:02", "11:22", "11:42", "12:12", "12:32", "12:52", "13:12", "13:32", "13:52", "14:12", "14:32", "14:42", "15:02", "15:32", "15:52", "16:12", "16:32", "16:52", "17:12", "17:32", "17:52", "18:12", "18:47", "19:23", "19:48", "20:28", "21:03", "21:33", "22:08", "22:40"]
I must put specific data to correct header. For example
05 06
05:01 06:03
05:23 06:33
05:43 06:53
Rails 3.0.3
Ruby 1.9.2
Prawn 0.8.4
How I can do that ?
Basically i want do something like this.
Prawn::Document.generate(path) do
table([['05','06']] + [['05:01','06:03'],['05:23','06:33'],['05:43','06:53']], :header => true) do
end
end
mapped_headers = headers.map do |header|
data_array = data.select {|d| header == d[0,2]}
[header, data_array]
end
This code will give output like this:
[["05", ["05:01", "05:23", "05:43"]], ["06", ["06:03", "06:33", "06:53"]], ["07", ["07:03", "07:23", "07:46"]], ["08", ["08:04", "08:24", "08:44"]], ["09", ["09:14", "09:24", "09:44"]], ["10", ["10:19", "10:39"]], ["11", ["11:02", "11:22", "11:42"]], ["12", ["12:12", "12:32", "12:52"]], ["13", ["13:12", "13:32", "13:52"]], ["14", ["14:12", "14:32", "14:42"]], ["15", ["15:02", "15:32", "15:52"]], ["16", ["16:12", "16:32", "16:52"]], ["17", ["17:12", "17:32", "17:52"]], ["18", ["18:12", "18:47"]], ["19", ["19:23", "19:48"]], ["20", ["20:28"]], ["21", ["21:03", "21:33"]], ["22", ["22:08", "22:40"]]]
You can also create a hash by editing last line
{header => data_array}
You can acheive Prawn requirement by doing this
rows = 3
datas = (0...rows).map do |row|
mapped_headers.map{|header| header[1][row]}
end
Prawn::Document.generate(path) do
table([headers] + datas, :header => true) do
end
end
If you are asking about how to add a new element to an array, method push will do the job:
headers.push "05"
data.push "05:01"

Resources