/app/controllers/spanish_sentence_quiz_controller.rb
Ruby | 352 lines | 244 code | 41 blank | 67 comment | 23 complexity | 742a52521c59c0827a4367b2c4c3c59e MD5 | raw file
- #encoding : utf-8
- #This File holds the SpanishSentencesQuizController class code,
- #which is used to interact with a JQuery module that displays
- #a quiz to fill in a correct blank word for a sentence
- #
- #
- #Author:: Brian Cowan (mailto:brian@briancowan.net)
- #Copyright:: Copyright (c) 2010 Brian Cowan for 123TeachMe.com
- #License:: Proprietary Code
- #Version:: $history$
- #
- class SpanishSentenceQuizController < ApplicationController
- caches_action :list, :category
-
- # List of all Sentence Match categories
- def list
- @page_title = 'Spanish Sentence Quizzes'
- @page_heading = @page_title
- if(params[:full]=='true') then
- @categories = TranslatedSentence.quiz_category_hash()
- else
- @widget=Widget.where('lookup="spanish_sentence_quiz"').first;
- end
- end
-
- #Go to a random next quiz
- def next_quiz
- categories = TranslatedSentence.quiz_category_hash()
- categories.delete_if{|k,v| v<8}
- num=rand(categories.length);
- cat_name = categories.keys[num];
- redirect_to :action=>"category",:id=>cat_name;
- end
-
- #Load rows from the database based upon simple boolean combination of categories
- #params:
- # :id = boolean tag command [coma separated (&tag |tag !tag)
- # :page = page of quizzes to display
- # :title = title to display for quizzes (default is additional sentences)
- # :group = optional WidgetCategoryGroup.lookup_key to load additional categories
- #out:
- # HTML:
- # Page with widget on given page with title
- # JSON:
- # {data=>
- # [ {:id=>row.id, /*currently unused*/
- # :english=>row.english,
- # :spanish=>row.spanish_sentence,
- # :correct=>row.correct_answer,
- # :incorrect=>row.wrong_answers,
- # :audio=>row.audio /*with added server http:// for relative dirs)*/
- # }]
- # }
- def category
- query=params[:id];
- return false if(
- (query.blank? && params[:group].blank?) ||
- (!query.blank? && (query.length>80 or !query.index("%").nil?))
- ) #To limit strange queries
-
- #Decompose query into and/or/not categories, and put group categories into ORs
- tags=query.split(',')
- ands=[]
- ors=[]
- nots=[]
-
-
-
- tags.each do |t|
- l=t[0..0]
- s=t[1..-1]
- if(l=="|") then
- ors << s
- elsif(l=="!") then
- nots << s
- elsif(l=="&") then
- ands << s
- else
- ors << t
- end
- end
-
- if(!params[:group].blank?)
- @grp=WidgetCategoryGroup.find_by_lookup_key(params[:group])
- if(!@grp.nil?) then
- #add all group categories that are not in params[:id]
- gc=@grp.categories.split('|').reject {|c| !ors.index(c).nil?}
- ors.concat(gc)
- end
- end
-
- qstring=""
- plist=[]
- ors.each do |s|
- qstring+="OR (quiz_categories=? OR quiz_categories LIKE ? OR quiz_categories LIKE ? OR quiz_categories LIKE ?) "
- plist << s
- plist << "%|"+s+"|%"
- plist << s+"|%"
- plist << "%|"+s
- end
- tmp1=
- if(qstring.blank?) then
- false
- else
- qstring="("+qstring[3..-1]+")"
- true
- end
- if(ands.length>0) then
- ands.each do |s|
- qstring+="AND (quiz_categories=? OR quiz_categories LIKE ? OR quiz_categories LIKE ? OR quiz_categories LIKE ?) "
- plist << s
- plist << "%|"+s+"|%"
- plist << s+"|%"
- plist << "%|"+s
- end
- qstring=qstring[4..-1] if(!tmp1)
- tmp1=true
- end
-
- if(nots.length>0) then
- nots.each do |s|
- qstring+="AND (quiz_categories <> ? AND quiz_categories NOT LIKE ? AND quiz_categories NOT LIKE ? AND quiz_categories NOT LIKE ?) "
- plist << s
- plist << "%|"+s+"|%"
- plist << s+"|%"
- plist << "%|"+s
- end
- qstring=qstring[4..-1] if(!tmp1)
- end
-
- qstring+=" AND (spanish IS NOT NULL AND english IS NOT NULL AND correct_answer IS NOT NULL AND wrong_answers IS NOT NULL)"
- data=[]
- tlist=[qstring]
- tlist.concat(plist)
-
- #Engine attrs
- @page_title = 'Spanish Sentence Quiz: ' + (@grp.nil? ? query.capitalize.gsub("_"," ") : @grp.name)
- @page_heading = @page_title
-
- #Build items
- TranslatedSentence.where(tlist).each do |sq|
-
- #verb might be in a different case in the sentence
- sp=sq.spanish
- ca=sq.correct_answer
- aud=sq.audio
- if (aud.blank?) then
- aud=nil
- elsif(aud.index("http")!=0) then
- #aud="http://static.123teachme.com"+aud ;
- end
-
-
- m=sp.upcase.match(Regexp.new('(\b|[żĄ])('+ca.upcase+')(\b)',true,'u'))
- if(!m.nil?) then
- i=m.begin(1)+m[1].length
- sqn=sp[0...i]+"___"+sp[(i+ca.length)..-1]
-
- data<<{
- :cats=>sq.quiz_categories,
- :english=>sq.english,
- :spanish=>sqn,
- :correct=>ca,
- :incorrect=>sq.wrong_answers.gsub("|",","),
- :audio=>aud
- }
- else
- #do a looser check
- i=sp.upcase.index(ca.upcase)
- if(!i.nil?) then
- sqn=sp[0...i]+"___"+sp[(i+ca.length)..-1]
- data<<{
- :cats=>sq.quiz_categories,
- :english=>sq.english,
- :spanish=>sqn,
- :correct=>ca,
- :incorrect=>sq.wrong_answers.gsub("|",","),
- :audio=>aud
- }
- else
- #Flag there is something strange with the data
- data<<{
- :cats=>sq.quiz_categories,
- :flag=>true,
- :id=>sq.id,
- :english=>sq.english,
- :spanish=>sp,
- :correct=>ca,
- :incorrect=>sq.wrong_answers.gsub("|",","),
- :audio=>aud
- }
- end
- end
- end
-
- #---step categories, so similar quizzes are not all next to each other
-
- #first separate data into categories
- data_tmp={}
- data.each do |i|
- data_tmp[i[:cats]]||=[]
- data_tmp[i[:cats]]<< i
- end
-
- #count how many are in each category and assign 0 to frequency weight
- full_count=data.length+0.0
- cat_cnt={}
- cat_weight={}
- cat_len=data_tmp.keys.length
- data_tmp.keys.each do |k|
- cat_cnt[k]=data_tmp[k].length+0.0
- cat_weight[k]=0.0
- end
-
- data=[]
-
- #now separate, putting one from each category weighted by how many elements are in that category
- while(!data_tmp.empty?) do
- data_ntmp={};
- data_tmp.keys.sort.each do |k|
- cat_weight[k]+=cat_cnt[k]/full_count
- ar=data_tmp[k].dup
- if(cat_weight[k]>1.0) then
-
- cat_weight[k]-=1.0
- i=ar.pop()
- i.delete(:cats); #cats unused in widget now, delete done for security and transmission efficiency
- data<< i
- if(!ar.empty?) then
- data_ntmp[k]=ar
- end
- else
- data_ntmp[k]=ar
- end
- end
- data_tmp=data_ntmp
- end
-
- #for extra quizzes
- @widget=Widget.where('lookup="spanish_sentence_quiz"').first
-
- respond_to do |f|
- f.html do
- @data=data
- end
- f.json do
- render :json=>{:data=>data}.to_json
- end
- end
-
- end
-
- #Load rows from the database
- #params:
- # :id = coma split list of rows
- # :page = page of quizzes to display
- # :title = title to display for quizzes (default is additional sentences)
- #out:
- # HTML:
- # page with widget on given page and title
- # JSON:
- # {data=>
- # [ {:id=>row.id, /*currently unused*/
- # :english=>row.english,
- # :spanish=>row.spanish_sentence,
- # :correct=>row.correct_answer,
- # :incorrect=>row.wrong_answers,
- # :audio=>row.audio /*with added server http:// for relative dirs)*/
- # }]
- # }
- def load_rows
- row_ids=params[:id].split(",")
-
- rows={}
- row_ids.each do |id|
- iid=id.to_i
- rows[id]=true if(iid.to_s==id)
- end
-
-
- data=[]
- vals=rows.keys.join(",")
- qstring="id in ("+vals+") AND (spanish IS NOT NULL AND english IS NOT NULL AND correct_answer IS NOT NULL AND wrong_answers IS NOT NULL)"
- sqs=TranslatedSentence.where(qstring).all
- sqs.each do |sq|
-
- #verb might be in a different case in the sentence
- sp=sq.spanish;
- ca=sq.correct_answer
-
- aud=sq.audio
- if (aud.blank?) then
- aud=nil
- elsif(aud.index("http")!=0) then
- #aud="http://static.123teachme.com"+aud
- end
-
- m=sp.upcase.match(Regexp.new('(\b|[żĄ])('+ca.upcase+')(\b)',true,'u'))
- if(!m.nil?) then
- i=m.begin(1)+m[1].length
-
- sqn=sp[0...i]+"___"+sp[(i+ca.length)..-1]
- data<<{
- :english=>sq.english,
- :spanish=>sqn,
- :correct=>ca,
- :incorrect=>sq.wrong_answers.gsub("|",","),
- :audio=>aud
- };
- else
- #do a looser check
- i=sp.upcase.index(ca.upcase)
- if(!i.nil?) then
- sqn=sp[0...i]+"___"+sp[(i+ca.length)..-1]
- data<<{
- :english=>sq.english,
- :spanish=>sqn,
- :correct=>ca,
- :incorrect=>sq.wrong_answers.gsub("|",","),
- :audio=>aud
- }
- else
- #Flag there is something strange with the data
- data<<{
- :flag=>true,
- :id=>sq.id,
- :english=>sq.english,
- :spanish=>sp,
- :correct=>ca,
- :incorrect=>sq.wrong_answers.gsub("|",","),
- :audio=>aud
- }
- end
- end
- end
- respond_to do |f|
- f.html do
- @data=data
- end
- f.json do
- render :json=>{:data=>data}.to_json
- end
- end
-
- end
- end