Calendar of a football championship - Answer set programming - calendar

I wrote an algorithm in answer set programming, run with clingo, to calculate a league of 20 teams and its 38 matches (19 round and 19 return) with certain constraints:
There may not be more than one match on the same day with two teams at home from the same city;
A team may not play more than two home games in a row.
Between a first match and a return match (same teams) must pass at least 10 days.
The problem is that the algorithm, performed in a test with 10 teams, ends in 20 seconds, while with 20 teams does not end in 24 hours..
Is there any way to optimize the algorithm, maybe by using counts or something?
This is the code:
squadra(
milan;
napoli;
inter;
juventus;
atalanta;
roma;
lazio;
fiorentina;
sassuolo;
verona;
torino;
bologna;
empoli;
udinese;
sampdoria;
spezia;
cagliari;
venezia;
genoa;
salernitana
).
citta(milan, milano).
citta(napoli, napoli).
citta(inter, milano).
citta(juventus, torino).
citta(atalanta, bergamo).
citta(roma, roma).
citta(lazio, roma).
citta(fiorentina, firenze).
citta(sassuolo, sassuolo).
citta(verona, verona).
citta(torino, torino).
citta(bologna, bologna).
citta(empoli, empoli).
citta(udinese, udine).
citta(sampdoria, genova).
citta(spezia, laspezia).
citta(cagliari, cagliari).
citta(venezia, venezia).
citta(genoa, genova).
citta(salernitana, salerno).
giornataAndata(1..19).
giornataRitorno(20..38).
% 10 partite per ogni giornata
10 {partita(G, SquadraCasa, SquadraTrasferta) : squadra(SquadraCasa), squadra(SquadraTrasferta), SquadraCasa <> SquadraTrasferta} 10 :- giornataAndata(G).
10 {partita(G, SquadraCasa, SquadraTrasferta) : squadra(SquadraCasa), squadra(SquadraTrasferta), SquadraCasa <> SquadraTrasferta} 10 :- giornataRitorno(G).
% Nella stessa giornata, una squadra non può giocare più di una partita.
% In giornate diverse, due squadre che si sono già incontrate, non si posso rincontrare.
:- giornataAndata(G), partita(G, SquadraCasa, SquadraTrasferta), partita(G, SquadraCasa, SquadraTrasferta2), SquadraTrasferta<>SquadraTrasferta2.
:- giornataAndata(G), partita(G, SquadraCasa, SquadraTrasferta), partita(G, SquadraCasa2, SquadraTrasferta), SquadraCasa<>SquadraCasa2.
:- giornataAndata(G), partita(G, SquadraCasa, SquadraTrasferta), partita(G, SquadraCasa2, SquadraTrasferta2), SquadraCasa==SquadraTrasferta2.
:- giornataAndata(G), partita(G, SquadraCasa, SquadraTrasferta), partita(G, SquadraCasa2, SquadraTrasferta2), SquadraTrasferta==SquadraCasa2.
:- giornataAndata(G), giornataAndata(G2), partita(G, SquadraCasa, SquadraTrasferta), partita(G2, SquadraCasa, SquadraTrasferta), G<>G2.
:- giornataAndata(G), giornataAndata(G2), partita(G, SquadraCasa, SquadraTrasferta), partita(G2, SquadraTrasferta, SquadraCasa), G<>G2.
:- giornataRitorno(G), partita(G, SquadraCasa, SquadraTrasferta), partita(G, SquadraCasa, SquadraTrasferta2), SquadraTrasferta<>SquadraTrasferta2.
:- giornataRitorno(G), partita(G, SquadraCasa, SquadraTrasferta), partita(G, SquadraCasa2, SquadraTrasferta), SquadraCasa<>SquadraCasa2.
:- giornataRitorno(G), partita(G, SquadraCasa, SquadraTrasferta), partita(G, SquadraCasa2, SquadraTrasferta2), SquadraCasa==SquadraTrasferta2.
:- giornataRitorno(G), partita(G, SquadraCasa, SquadraTrasferta), partita(G, SquadraCasa2, SquadraTrasferta2), SquadraTrasferta==SquadraCasa2.
:- giornataRitorno(G), giornataRitorno(G2), partita(G, SquadraCasa, SquadraTrasferta), partita(G2, SquadraCasa, SquadraTrasferta), G<>G2.
:- giornataRitorno(G), giornataRitorno(G2), partita(G, SquadraCasa, SquadraTrasferta), partita(G2, SquadraTrasferta, SquadraCasa), G<>G2.
:- giornataAndata(G), partita(G, SquadraCasa, SquadraTrasferta), partita(G, SquadraCasa2, SquadraTrasferta2), SquadraCasa<>SquadraCasa2, citta(SquadraCasa, C), citta(SquadraCasa2, C).
:- giornataRitorno(G), partita(G, SquadraCasa, SquadraTrasferta), partita(G, SquadraCasa2, SquadraTrasferta2), SquadraCasa<>SquadraCasa2, citta(SquadraCasa, C), citta(SquadraCasa2, C).
:- giornataAndata(GA), giornataRitorno(GR), partita(GA, SquadraCasa, SquadraTrasferta), partita(GR, SquadraCasa, SquadraTrasferta).
:- giornataAndata(G),
partita(G, SquadraCasa, SquadraTrasferta),
partita(G+1, SquadraCasa, SquadraTrasferta2),
partita(G+2, SquadraCasa, SquadraTrasferta3).
:- giornataRitorno(G),
G<=36,
partita(G, SquadraCasa, SquadraTrasferta),
partita(G+1, SquadraCasa, SquadraTrasferta2),
partita(G+2, SquadraCasa, SquadraTrasferta3).
:- giornataAndata(GA),
giornataRitorno(GR),
GR<=29,
partita(GA, SquadraCasa, SquadraTrasferta),
partita(GR, SquadraTrasferta, SquadraCasa),
Risultato = GR-GA,
Risultato <= 10.
#show partita/3.
SquadraCasa = Home team.
SquadraTrasferta = Away team.
G = number of day.
partita(G, SquadraCasa, SquadraTrasferta) = match(G, HomeTeam, AwayTeam).
giornataAndata(1..19) = first half of the season(1..19).
giornataRitorno(20..38) = second half of the season(20..38).
citta(milan, milano) = the team "Milan" play in the city of Milan.
squadra(milan; napoli; ...) = team(milan; napoli; ...).
Thank you very much in advance!

I have bad news for you: your program seems unsatisfiable.
I rewrote the code since there are redundancies, and I came up with this:
player(milan; napoli; inter; juventus; atalanta; roma; lazio; fiorentina; sassuolo; verona; torino; bologna; empoli; udinese; sampdoria; spezia; cagliari; venezia; genoa; salernitana).
n(N):- {player(X)} = N. % counting players
citta(milan, milano).
citta(napoli, napoli).
citta(inter, milano).
citta(juventus, torino).
citta(atalanta, bergamo).
citta(roma, roma).
citta(lazio, roma).
citta(fiorentina, firenze).
citta(sassuolo, sassuolo).
citta(verona, verona).
citta(torino, torino).
citta(bologna, bologna).
citta(empoli, empoli).
citta(udinese, udine).
citta(sampdoria, genova).
citta(spezia, laspezia).
citta(cagliari, cagliari).
citta(venezia, venezia).
citta(genoa, genova).
citta(salernitana, salerno).
dates(1..2*(N-1)) :- n(N).
date1(1..N-1) :- n(N).
date2(N..2*N-2) :- n(N).
1{game(T,X,Y):dates(T)}1:- player(X),player(Y), X<>Y.
(N/2){ game(T,X,Y): player(X), player(Y), X<>Y }(N/2) :- dates(T), n(N).
:- player(X), player(Y), game(G1,X,Y), game(G2,Y,X), G1<G2, date2(G1).
:- player(X), player(Y), game(G1,X,Y), game(G2,Y,X), G1<G2, date1(G2).
:- player(X), game(G,X,_), game(G+1,X,_), game(G+2,X,_).
:- player(X), player(Y), game(G1,X,Y), game(G2,Y,X), G1<G2, G2-G1<=N, n(N).
:- dates(T), game(T,X,_), game(T,Y,_), citta(X,Z), citta(Y,Z).
which returns unsatisfiable. If you comment the last line out you will get a model. Please note that I took some liberty interpreting your work.

Related

What are these numbers used for chinese lunar calendar conversions?

I'm developing an application about bank holidays in many countries.
To find bank holidays dates in China I need to convert dates to Chinese system.
I have found many libraries in different languages, like :
this one : https://github.com/v5developer/maven-framework-project/blob/master/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/LunarCalendar.java that I transposed to Apex language
this one https://www.javascriptbank.com/javascript/time/Lunar_Calendar_script/amlich-hnd.js in js (it's for Vietnam but seems to work about the same)
or this one https://github.com/magiclen/JavaChineseCalendar/blob/master/src/main/java/org/magiclen/%E8%BE%B2%E6%9B%86/%E8%BE%B2%E6%9B%86.java
and more.
All of them use an array of numbers, with one number per year, like this one :
final static long[] lunarInfo = new long[] { 0x04bd8, 0x04ae0, 0x0a570,
0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2,
0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0,
0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50,
0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566,
0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0,
0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4,
0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550,
0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950,
0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260,
0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0,
0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6,
0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40,
0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 0x074a3,
0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0, 0x0c960,
0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0,
0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9,
0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0,
0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65,
0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0,
0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2,
0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0 };
used to calculate various numbers, like in
final private static int yearDays(int y) {
int i, sum = 348;
for (i = 0x8000; i > 0x8; i >>= 1) {
if ((lunarInfo[y - 1900] & i) != 0)
sum += 1;
}
return (sum + leapDays(y));
}
final private static int leapDays(int y) {
if (leapMonth(y) != 0) {
if ((lunarInfo[y - 1900] & 0x10000) != 0)
return 30;
else
return 29;
} else
return 0;
}
I've been searching in libraries comments, documentations, gerneral info about China, and I learnt a lot about the chinese calendar but couldn't find what these numbers are.... and where they come from.
It doesn't prevent me from using it but I like to understand what I code... Any explanations ?
Thanks
I finally came to understand that, at least for this code https://github.com/v5developer/maven-framework-project/blob/master/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/LunarCalendar.java, it's just a way to store data :
The data is encoded on 17 bits with :
bit 17 : number of days in leap month , 1=>30, 0=>29
bits 16 to 5 : number of days in each month, 0=>29, 1=>30
bits 4 to 1 : number of the leap month in the year in binary.
So 0x16554 (7th in the list, so year 1906) is 10110010101010100 in binary with a 17 bits length, which means :
10110010101010100 : There is a leap month, it's month 4
10110010101010100 : The leap month has 30 days
10110010101010100 : The 1st month has 29 days
10110010101010100 : The 2nd month has 30 days
...
10110010101010100 : The 12th month has 30 days
which can be checked here : https://www.asia-home.com//china/calendrier-chinois/year/1906.php
In other codes the meaning can vary but the idea is the same.

reactjs datepicker date format

Beginner with ReactJS, I use now the wonderful ReactJS Datepicker. Questions about my custom date format :
i found no doc to explain all the possibilities like M is month, MM is month on 2 letters, etc. (shall I look to the github code? which source?)
How to add the name of the day... like Saturday. I tried dddd but it shows the number of the day with 2 leading 0 before !!
How to exclude the non office hour (like hours 0 to 8 and 20 to 23), I tried the excludesTimes below but no way.
Here is my code :
<DatePicker
selected={this.state.startDate}
onChange={this.handleChange}
locale={fr}
showTimeSelect
timeFormat="HH:mm"
timeIntervals={60}
dateFormat="dddd, DDD, ddd, d, dd MMMM yyyy à HH'h'mm"
timeCaption="Heure"
minDate={new Date()}
showDisabledMonthNavigation
placeholderText="Choisir ici ..."
excludeTimes={[0, 1, 2, 3, 4]}
/>
Date shown in input field is then :
0023, 082, 023, 23, 23 mars 2019 à 20h00
Thanks
React datepicker uses Moment.js for dates, I think you should review the docs at his website.
For example MMMM Do YYYY, h:mm:ss a should return a date formated as March 21st 2019, 8:50:37 am.
EDIT
I went to the repo and it appears the author removed moment from package, so I gave a try to the formatting dates guide found here and it appears to be working now! Per example use "eeee" if you want day of the week.
I made a working example at codesandbox.
You also can convert manually ...
const convertDate = str => {
str = str.toString();
let parts = str.split(" ");
let months = {
Jan: "01",
Feb: "02",
Mar: "03",
Apr: "04",
May: "05",
Jun: "06",
Jul: "07",
Aug: "08",
Sep: "09",
Oct: "10",
Nov: "11",
Dec: "12"
};
return parts[3] + "-" + months[parts[1]] + "-" + parts[2];
};
:) Reinventing the wheel

How to have upper case methods in ruby

I got a chatbot in ruby that if a character is repeated five times or more in the chat, in the first and second attempt, it warns the user, at the third attempt it kicks the user and the fourth one bans the user for two hours, and it's currently working
require_relative '../plugin'
class Flood
include Chatbot::Plugin
match /(.*)/, :method => :check_swear, :use_prefix => false
def initialize(bot)
super(bot)
#data = {}
end
def check_swear(user, message)
message = message.downcase
array = ["aaaaa", "ñññññ", "bbbbb", "ccccc", "ddddd", "eeeee", "fffff", "ggggg", "hhhhh", "iiiii", "jjjjj", "mmmmm", ".....", "*****", "?????", "!!!!!", "zzzzz", "kkkkkk", "ooooo", "nnnnn", "ppppp", "qqqqq", "rrrrr", "-----", "_____", "¨¨¨¨¨¨¨¨", "{{{{{", "}}}}}", "#####"]
array.each do |e|
if message.include? e
if(#data[user.name] and #data[user.name] == 3)
#client.send_msg "%s: [[Wiki_Freddy_Fazbear's_Pizza:Reglas_y_Lineamientos|Has sido advertido. Tendrás un ban de 2 horas.]] 4/3" % user.name
#client.ban user.name, "7200", "Ban automático por exceso de carácteres - Si crees que esto fué un error, contacta con un [[Wiki_Freddy_Fazbear%27s_Pizza:Administradores|moderador u Admin en su muro de mensajes]]."
#client.send_msg "!mods por si acaso consideran necesario más tiempo de ban."
#client.kick user.name
#data[user.name] = 0
elsif(#data[user.name] and #data[user.name] == 2)
#data[user.name] ||= 0
#data[user.name] += 1
#client.send_msg "%s: [[Wiki_Freddy_Fazbear's_Pizza:Reglas_y_Lineamientos|Por favor, no repitas carácteres, última advertencia antes de un ban.]] 3/3" % user.name
#client.kick user.name
elsif(#data[user.name] and #data[user.name] == 1)
#data[user.name] ||= 0
#data[user.name] += 1
#client.send_msg "%s: [[Wiki_Freddy_Fazbear's_Pizza:Reglas_y_Lineamientos|Por favor, no repitas carácteres, última advertencia antes de un kick]], 2/3" % user.name
else
#data[user.name] ||= 0
#data[user.name] += 1
#client.send_msg "%s: [[Wiki_Freddy_Fazbear's_Pizza:Reglas_y_Lineamientos|Por favor, no repitas carácteres]], 1/3" % user.name
end
end
end
end
end
Now, I need to change it, being all the same except for that it does not trigger with 5 characters or more, but if 5 or more words in a message are in capital letters, can someone help me?
Edit: By the way, if someone can also help me to make it trigger not just with the characters in the array list but any character, it would be awesome
Something like the following will return true if a message has 5 or more uppercase words.
def is_message_shouting?(message)
shouted_words = 0
message.split(' ').each do |word|
shouted_words += 1 if word.upcase == word
end
shouted_words >= 5
end
puts is_message_shouting? 'THIS IS A VERY SHOUTY MESSAGE'
puts is_message_shouting? 'this is not a shouty message'
puts is_message_shouting? 'THIS IS ALSO not a shouty message'
Outputs:
true
false
false
def shouting?(message)
message.split.count { |word| word == word.upcase } >= 5
end
Nothing original to add, just a cleaner implementation of the same.
Something like
class String
def is_upper?
self == self.upcase
end
end
def shouting?(msg)
count = 0
0.upto(msg.size) { |i| count += 1 if msg[i].is_upper? }
count >= 5
end

C beginner help : day of week for any given date

The prompt is:
Implement a function that reads in a string containing a textual description of a cal- endar date and that prints out the corresponding day of the week (Monday–Sunday). The two valid input formats for this function are:
mm/dd/yyyy
Example: 03/04/2014
Output: Tuesday
Month dd, yyyy
Example: March 04, 2014
Output: Tuesday
where dd is the numeric day, mm is the numeric month, yyyy is the year and Month is the name of the month. All days and months are specified using two digits (i.e. for March, use 03 instead of 3). In the second valid format, there is a single space between Month and dd and between dd, and yyyy.
In order to receive full credit on this task, your program should print out the correct day of the week for any input in a correct format.
So as of right now i am able to get the correct days for every single day except in the years 2005 2009 2013 2017 etc etc... they are always a day behind, i notice that its going by a trend of every 4 years the days end up 1 day behind. Im not sure whats wrong. is it cause my method of using 365.25 as each year is wrong?
My code:
#include<stdio.h>
int main()
{
int month,day1,day2,totdays,year,dm,dn,leap,rmd;
printf(" ");
scanf("%d/%d/%d",&month,&day1,&year);
if(((year%4==0) && (year%100!=0)) || (year%400==0))
{
if(month==1)
dm=0;
if(month==2)
dm=31;
if(month==3)
dm=60;
if(month==4)
dm=91;
if(month==5)
dm=121;
if(month==6)
dm=152;
if(month==7)
dm=182;
if(month==8)
dm=213;
if(month==9)
dm=244;
if(month==10)
dm=274;
if(month==11)
dm=305;
if(month==12)
dm=335;
}
else
{
if(month==1)
dm=0;
if(month==2)
dm=31;
if(month==3)
dm=59;
if(month==4)
dm=90;
if(month==5)
dm=120;
if(month==6)
dm=151;
if(month==7)
dm=181;
if(month==8)
dm=212;
if(month==9)
dm=243;
if(month==10)
dm=273;
if(month==11)
dm=304;
if(month==12)
dm=334;
}
day2=(year-1970)*(365.25);
dn=dm+day1;
totdays=day2+dn;
rmd=totdays%7;
if(rmd==5)
{
printf("Monday \n");
}
if(rmd==6)
{
printf("Tuesday \n");
}
if(rmd==0)
{
printf("Wednesday \n");
}
if(rmd==1)
{
printf("Thursday \n");
}
if(rmd==2)
{
printf("Friday \n");
}
if(rmd==3)
{
printf("Saturday \n");
}
if(rmd==4)
{
printf("Sunday \n");
}
return 0;
}
1969 wasn't a leap year, 1972 was. When you do
day2=(year-1970)*(365.25);
to discover how many days off January 1st of year year is, you'll count
0 days for '70
365.25 days for '71
730.5 days for '72
1095.75 days for '73
1461 days for '74
The fractional portion of the floating point calculation is truncated, so day2 isn't going to count the extra day from 02/29/1972 until 01/01/1974, instead of 01/01/1973 as it should.
Put another way, you are making the assumption that 1970 was the first year after a leap year, so a leap day won't be counted until four years later.
The day2 calculation won't work. There are 1461 days in every four year period. First you need to compute how many 4 year periods have passed. Then figure out how many days there were to the beginning of the specified year, similar to what you did for the months.
The year%100 and year%400 exceptions add a little complexity, but fortunately the year 2000 was a leap year, so the first time you have to deal with that little wrinkle is the year 2100.

Store several text_field strings to array Rails 3

I'm trying to store some strings from a couple of text_fields that i have into an array, and then save it to the DB.
I have a column named "opening_hours" wich I've tried to separate into 2 different attributes using virtual attributes like this:
Model
class Venue < ActiveRecord::Base
attr_accessible :opening_hours, :start_time, :end_time
attr_writer :start_time, :end_time
def start_time
#start_time.nil? ? #start_time : opening_hours.to_s.split("-").first
end
def end_time
#end_time.nil? ? #end_time : opening_hours.to_s.split("-").last
end
end
The idea is that you type in a start_time and an end_time like this:
View
<%= form_for #venue do |v| %>
<p><%= v.label "Monday" %><%= v.text_field :start_time %>-<%= v.text_field :end_time %><p/>
<p><%= v.label "Tuesday" %><%= v.text_field :start_time %>-<%= v.text_field :end_time %><p/>
<p><%= v.label "Wednesday" %><%= v.text_field :start_time %>-<%= v.text_field :end_time %><p/>
<% end %>
The array should look something like this in the DB:
{08-12|09-14|07-13}
With the "|" separating the different days of the week.
I've tried a couple of things in the controller like:
Controller
class VenuesController < ApplicationController
def new
#venue = Venue.new
end
def create
#venue = Venue.new(params[:venue])
#total_time = params[:venue][:start_time]+"-"+params[:venue][:end_time]
#venue.opening_hours = #total_time.map {|t| [t.start_time, t.end_time]}
if #venue.save
redirect_to venue_path(#venue), :notice => "Success!"
else
render 'new'
end
end
But nothing seems to work... either it just saves start_time and end_time from the last day, or nothing gets saved at all.
I perhaps may have misunderstood, but...
In your create action, there is no #venue.save - this could be why you are not seeing anything saved.
class VenuesController < ApplicationController
def new
#venue = Venue.new
end
def create
#venue = Venue.new(params[:venue])
#total_time = params[:venue][:start_time]+"-"+params[:venue][:end_time]
#venue.opening_hours = #total_time.map {|t| [t.start_time, t.end_time]}
#venue.save
end
end
Your solution will not work, since you place three text-fields each pointing to the same field. Rails will just take the last value.
Rails will use the name of the input field to construct the parameters hash you receive at the server. Since the fields have the same name, only one value will remain.
The solution is pretty simple: using the same rails standards, we can change the name of the input fields so rails will handle it as a hash.
<p>
<%= v.label "Monday" %>
<%= text_field :venue, 'start_time[][monday]', :value => '07' %>
<%= text_field :venue, 'end_time[][monday]', :value => '21' %>
<p/>
<p>
<%= v.label "Tuesday" %>
<%= text_field :venue, 'start_time[][tuesday]', :value => '07' %>
<%= text_field :venue, 'end_time[][tuesday]', :value => '09' %>
<p/>
Since end_time and start_time is not a array, I have to fake it a bit, so I use a manual text_field, use as object-name venue so it will be grouped with the rest of the parameters for your venue. Then I build the name, so rails will compose a hash with the values entered. Note, you have to explicitly define a value, or this will not work.
Then, in the controller, you will have to add some code to
when editing, convert the array-string to values in your form
when saving, convert the recevied hash to a string you can save.
Note: if you do not, it will save the serialized hash, which might just be enough already.

Resources