Added joined leagues to defs system (e.g. for US conferences).

This commit is contained in:
gyboth 2008-11-20 20:20:18 +00:00
parent 4df9946310
commit 73d4cc6795
12 changed files with 261 additions and 21 deletions

View File

@ -42,21 +42,58 @@
void
fixture_write_league_fixtures(League *league)
{
gint round_robins = league->round_robins;
GPtrArray *teams = NULL;
gint i,j;
gint max_rr;
gint joined_clids[league->joined_leagues->len];
gint joined_rrs[league->joined_leagues->len];
GPtrArray *teams;
max_rr = league->round_robins;
teams = team_get_pointers_from_array(league->teams, NULL);
g_array_free(league->fixtures, TRUE);
league->fixtures = g_array_new(FALSE, FALSE, sizeof(Fixture));
while(round_robins > 0)
/** Add all teams to the same pointer array. */
for(i = 0; i < league->joined_leagues->len; i++)
{
teams = team_get_pointers_from_array(league->teams);
fixture_write_round_robin((gpointer)league, -1, teams, (round_robins == 1));
round_robins -= (round_robins > 1) ? 2 : 1;
joined_rrs[i] = g_array_index(league->joined_leagues, JoinedLeague, i).rr;
joined_clids[i] = league_index_from_sid(g_array_index(league->joined_leagues, JoinedLeague, i).sid);
max_rr = MAX(joined_rrs[i], max_rr);
teams = team_get_pointers_from_array(lig(joined_clids[i]).teams, teams);
}
/** Write fixtures for as many round robins as required by the maximum number of rrs given. */
for(i = 0; i < max_rr;)
{
fixture_write_round_robin((gpointer)league, -1, misc_copy_ptr_array(teams), (i == max_rr - 1));
i += (i < max_rr - 1) ? 2 : 1;
}
g_ptr_array_free(teams, TRUE);
g_array_sort_with_data(league->fixtures, fixture_compare_func,
GINT_TO_POINTER(FIXTURE_COMPARE_DATE + 100));
if(league->joined_leagues->len > 0)
{
/** Remove fixtures involving only teams from the joined leagues and
for joined leagues with a smaller number of rrs than the maximum. */
for(i = 0; i < league->joined_leagues->len; i++)
{
if(joined_rrs[i] < max_rr)
fixture_remove_rrs(league->fixtures, league->id, lig(joined_clids[i]).id, max_rr - joined_rrs[i]);
for(j = i; j < league->joined_leagues->len; j++)
fixture_remove_rrs(league->fixtures, lig(joined_clids[i]).id, lig(joined_clids[j]).id, max_rr);
}
/** Remove fixtures for reduced number of rrs. */
if(league->round_robins < max_rr)
fixture_remove_rrs(league->fixtures, league->id, league->id, max_rr - league->round_robins);
/** Move matches to earlier weeks if possible. */
fixtures_condense(league->fixtures);
}
}
/** Write the fixtures for the given cup
@ -1419,3 +1456,109 @@ fixture_get_last_scheduled_week(void)
return week_nr;
}
/** Remove a number of round robin from a fixture array.
@fixtures: The fixture array.
@clid1: The league id for one team.
@clid2: The league id for the second team.
@to_remove: How many matches to remove per pairing. */
void
fixture_remove_rrs(GArray *fixtures, gint clid1, gint clid2, gint to_remove)
{
gint i, j, k;
gint removed;
gint start;
League *league1, *league2;
league1 = league_from_clid(clid1);
league2 = league_from_clid(clid2);
for(i = 0; i < league1->teams->len; i++)
{
start = (clid1 == clid2) ? i + 1 : 0;
for(j = start; j < league2->teams->len; j++)
{
removed = 0;
for(k = fixtures->len - 1; k >= 0; k--)
if((g_array_index(fixtures, Fixture, k).teams[0]->id == g_array_index(league1->teams, Team, i).id &&
g_array_index(fixtures, Fixture, k).teams[1]->id == g_array_index(league2->teams, Team, j).id) ||
(g_array_index(fixtures, Fixture, k).teams[1]->id == g_array_index(league1->teams, Team, i).id &&
g_array_index(fixtures, Fixture, k).teams[0]->id == g_array_index(league2->teams, Team, j).id))
{
g_array_remove_index(fixtures, k);
removed++;
if(removed == to_remove)
break;
}
}
}
}
/** Move matches in the fixture array to earlier dates if possible. */
void
fixtures_condense(GArray *fixtures)
{
gint i, j, k, l;
GArray *matchday_teams[1000][5];
Fixture *fix;
gboolean fix_moved;
fix_moved = TRUE;
while(fix_moved)
{
fix_moved = FALSE;
for(i = 0; i < 1000; i++)
for(j = 0; j < 5; j++)
matchday_teams[i][j] = NULL;
for(i = 0; i < ligs->len; i++)
for(j = 0; j < lig(i).fixtures->len; j++)
{
fix = &g_array_index(lig(i).fixtures, Fixture, j);
if(matchday_teams[fix->week_number - 1][fix->week_round_number - 1] == NULL)
matchday_teams[fix->week_number - 1][fix->week_round_number - 1] = g_array_new(FALSE, FALSE, sizeof(gint));
g_array_append_val(matchday_teams[fix->week_number - 1][fix->week_round_number - 1], fix->teams[0]->id);
g_array_append_val(matchday_teams[fix->week_number - 1][fix->week_round_number - 1], fix->teams[1]->id);
}
for(i = fixtures->len - 1; i >= 0; i--)
{
fix = &g_array_index(fixtures, Fixture, i);
for(j = 0; j <= fix->week_number - 2; j++)
{
for(k = 0; k < 5; k++)
{
if(matchday_teams[j][k] != NULL)
{
for(l = 0; l < matchday_teams[j][k]->len; l++)
if(g_array_index(matchday_teams[j][k], gint, l) == fix->teams[0]->id ||
g_array_index(matchday_teams[j][k], gint, l) == fix->teams[1]->id)
break;
if(l == matchday_teams[j][k]->len)
{
fix_moved = TRUE;
fix->week_number = j + 1;
fix->week_round_number = k + 1;
g_array_append_val(matchday_teams[j][k], fix->teams[0]->id);
g_array_append_val(matchday_teams[j][k], fix->teams[1]->id);
}
}
}
}
}
for(i = 0; i < 1000; i++)
for(j = 0; j < 5; j++)
if(matchday_teams[i][j] != NULL)
g_array_free(matchday_teams[i][j], TRUE);
g_array_sort_with_data(fixtures, fixture_compare_func,
GINT_TO_POINTER(FIXTURE_COMPARE_DATE + 100));
}
}

View File

@ -162,4 +162,10 @@ fixture_count_matchdays(const GArray *fixtures);
gint
fixture_get_last_scheduled_week(void);
void
fixture_remove_rrs(GArray *fixtures, gint clid1, gint clid2, gint to_remove);
void
fixtures_condense(GArray *fixtures);
#endif

View File

@ -335,6 +335,8 @@ free_league(League *league)
if(league->teams != NULL)
free_teams_array(&league->teams, FALSE);
free_joined_leagues(&league->joined_leagues);
free_g_array(&league->teams);
free_g_array(&league->prom_rel.elements);;
@ -348,6 +350,18 @@ free_league(League *league)
free_league_stats(&league->stats);
}
/** Free the data in the joined leagues array. */
void
free_joined_leagues(GArray **joined_leagues)
{
gint i;
for(i = 0; i < (*joined_leagues)->len; i++)
free_gchar_ptr(g_array_index(*joined_leagues, JoinedLeague, i).sid);
free_g_array(joined_leagues);
}
/** Free the league stats. */
void
free_league_stats(LeagueStat *stats)

View File

@ -65,6 +65,9 @@ free_leagues_array(GArray **leagues, gboolean reset);
void
free_league(League *league);
void
free_joined_leagues(GArray **joined_leagues);
void
free_teams_array(GArray **teams, gboolean reset);

View File

@ -67,8 +67,8 @@ league_new(gboolean new_id)
new.prom_rel.elements = g_array_new(FALSE, FALSE, sizeof(PromRelElement));
new.teams = g_array_new(FALSE, FALSE, sizeof(Team));
new.fixtures = g_array_new(FALSE, FALSE, sizeof(Fixture));
new.joined_leagues = g_array_new(FALSE, FALSE, sizeof(JoinedLeague));
new.table = table_new();
new.table.clid = new.id;

View File

@ -77,6 +77,19 @@ typedef struct
gchar *prom_games_cup_sid;
} PromRel;
/**
A structure describing a different league joined to the current one
in the sense that there are matches played between teams from both leagues
like in the US conference system.
*/
typedef struct
{
/** Sid of the joined league. */
gchar *sid;
/** How many round robins to schedule. */
gint rr;
} JoinedLeague;
/**
Representation of a league.
@see PromRel
@ -105,7 +118,7 @@ typedef struct
there should be two matches in a week instead of one. */
GArray *two_match_weeks[2];
/** How many round robins are played. Important for
small leagues with 10 teams or so. Default: 1. */
small leagues with 10 teams or so. Default: 2. */
gint round_robins;
/** Number of weeks between the parts of a round robin. */
gint rr_break;
@ -117,6 +130,9 @@ typedef struct
/** Array of teams in the league.
@see Team */
GArray *teams;
/** List of leagues joined fixture-wise to this one.
@see JoinedLeague */
GArray *joined_leagues;
/** League table.
@see Table */
Table table;

View File

@ -116,8 +116,7 @@ misc_separate_strings(gchar *string)
return string_array;
}
/** Write a pointer array randomly into another one and free
the original one.
/** Write a pointer array randomly into another one and free the original array.
@param array The array to randomise.
@return A new pointer array containing the items in random order. */
GPtrArray*
@ -512,7 +511,7 @@ misc_string_replace_expressions(gchar *string)
gchar *occurrence = NULL,
*occurrence2 = NULL;
if(debug > 100)
if(debug > 200)
g_print("misc_string_replace_expressions: #%s#\n",
string);

View File

@ -110,14 +110,16 @@ table_update_get_elements(TableElement **elements, const Fixture *fix)
if(fix->clid < ID_CUP_START)
{
table = &league_from_clid(fix->clid)->table;
for(i=0;i<table->elements->len;i++)
{
if(g_array_index(table->elements, TableElement, i).team == fix->teams[0])
elements[0] = &g_array_index(table->elements, TableElement, i);
else if(g_array_index(table->elements, TableElement, i).team == fix->teams[1])
elements[1] = &g_array_index(table->elements, TableElement, i);
}
for(j = 0; j < 2; j++)
{
table = &league_from_clid(fix->teams[j]->clid)->table;
for(i=0;i<table->elements->len;i++)
{
if(g_array_index(table->elements, TableElement, i).team == fix->teams[j])
elements[j] = &g_array_index(table->elements, TableElement, i);
}
}
}
else
for(i=0;i<cup_get_last_tables(fix->clid)->len;i++)

View File

@ -183,9 +183,10 @@ query_team_is_in_cup(const Team *tm, const Cup *cup)
/** Return a GPtrArray containing the pointers
to the teams from the teams array.
@param teams The teams array we use.
@param team_ptrs NULL or a pointer array we append to
@return A GPtrArray containing pointers to the teams. */
GPtrArray*
team_get_pointers_from_array(const GArray *teams)
team_get_pointers_from_array(const GArray *teams, GPtrArray *team_ptrs)
{
gint i;
GPtrArray *team_pointers = g_ptr_array_new();
@ -193,6 +194,14 @@ team_get_pointers_from_array(const GArray *teams)
for(i=0;i<teams->len;i++)
g_ptr_array_add(team_pointers, (gpointer)&g_array_index(teams, Team, i));
if(team_ptrs != NULL)
{
for(i = 0; i < team_ptrs->len; i++)
g_ptr_array_add(team_pointers, g_ptr_array_index(team_ptrs, i));
g_ptr_array_free(team_ptrs, TRUE);
}
return team_pointers;
}

View File

@ -59,7 +59,7 @@ gboolean
query_team_is_in_cup(const Team *tm, const Cup *cup);
GPtrArray*
team_get_pointers_from_array(const GArray *teams);
team_get_pointers_from_array(const GArray *teams, GPtrArray *team_ptrs);
Team*
team_of_id(gint id);

View File

@ -52,6 +52,7 @@
#define TAG_NAMES_FILE "names_file"
#define TAG_ACTIVE "active"
#define TAG_BREAK "break"
#define TAG_JOINED_LEAGUE "joined_league"
#define TAG_PROM_REL "prom_rel"
#define TAG_PROM_GAMES "prom_games"
#define TAG_PROM_GAMES_DEST_SID "prom_games_dest_sid"
@ -73,6 +74,8 @@
#define TAG_TWO_MATCH_WEEK_START "two_match_week_start"
#define TAG_TWO_MATCH_WEEK_END "two_match_week_end"
#define ATT_NAME_JOINED_LEAGUE_RR "rr"
/**
* Enum with the states used in the XML parser functions.
*/
@ -110,6 +113,7 @@ enum XmlLeagueStates
STATE_TEAM_AVERAGE_TALENT,
STATE_TEAM_DEF_FILE,
STATE_BREAK,
STATE_JOINED_LEAGUE,
STATE_TWO_MATCH_WEEK_START,
STATE_TWO_MATCH_WEEK_END,
STATE_END
@ -139,6 +143,7 @@ xml_league_read_start_element (GMarkupParseContext *context,
{
PromRelElement new_element;
Team new_team;
JoinedLeague new_joined_league;
if(strcmp(element_name, TAG_LEAGUE) == 0)
{
@ -171,6 +176,17 @@ xml_league_read_start_element (GMarkupParseContext *context,
state = STATE_ACTIVE;
else if(strcmp(element_name, TAG_BREAK) == 0)
state = STATE_BREAK;
else if(strcmp(element_name, TAG_JOINED_LEAGUE) == 0)
{
state = STATE_JOINED_LEAGUE;
new_joined_league.sid = NULL;
if(attribute_names[0] != NULL && strcmp(attribute_names[0], ATT_NAME_JOINED_LEAGUE_RR) == 0)
new_joined_league.rr = (gint)g_ascii_strtod(attribute_values[0], NULL);
else
new_joined_league.rr = 2;
g_array_append_val(new_league.joined_leagues, new_joined_league);
}
else if(strcmp(element_name, TAG_TWO_MATCH_WEEK_START) == 0)
state = STATE_TWO_MATCH_WEEK_START;
else if(strcmp(element_name, TAG_TWO_MATCH_WEEK_END) == 0)
@ -252,6 +268,7 @@ xml_league_read_end_element (GMarkupParseContext *context,
strcmp(element_name, TAG_NAMES_FILE) == 0 ||
strcmp(element_name, TAG_ACTIVE) == 0 ||
strcmp(element_name, TAG_BREAK) == 0 ||
strcmp(element_name, TAG_JOINED_LEAGUE) == 0 ||
strcmp(element_name, TAG_TWO_MATCH_WEEK_START) == 0 ||
strcmp(element_name, TAG_TWO_MATCH_WEEK_END) == 0 ||
strcmp(element_name, TAG_PROM_REL) == 0 ||
@ -336,6 +353,11 @@ xml_league_read_text (GMarkupParseContext *context,
new_league.active = int_value;
else if(state == STATE_BREAK)
new_league.rr_break = int_value;
else if(state == STATE_JOINED_LEAGUE)
misc_string_assign(
&g_array_index(new_league.joined_leagues,
JoinedLeague,
new_league.joined_leagues->len - 1).sid, buf);
else if(state == STATE_TWO_MATCH_WEEK_START)
g_array_append_val(new_league.two_match_weeks[0], int_value);
else if(state == STATE_TWO_MATCH_WEEK_END)

View File

@ -54,6 +54,8 @@ enum
TAG_LEAGUE_PROM_REL_ELEMENT_DEST_SID,
TAG_LEAGUE_PROM_REL_ELEMENT_TYPE,
TAG_LEAGUE_BREAK,
TAG_LEAGUE_JOINED_LEAGUE_SID,
TAG_LEAGUE_JOINED_LEAGUE_RR,
TAG_LEAGUE_TWO_MATCH_WEEK_START,
TAG_LEAGUE_TWO_MATCH_WEEK_END,
TAG_END
@ -74,7 +76,10 @@ xml_loadsave_league_start_element (GMarkupParseContext *context,
gint i;
gint tag = xml_get_tag_from_name(element_name);
gboolean valid_tag = FALSE;
JoinedLeague new_joined_league;
new_joined_league.sid = NULL;
for(i=TAG_LEAGUE;i<TAG_END;i++)
if(tag == i)
{
@ -95,6 +100,9 @@ xml_loadsave_league_start_element (GMarkupParseContext *context,
promrankidx = 0;
}
if(tag == TAG_LEAGUE_JOINED_LEAGUE_SID)
g_array_append_val(new_league->joined_leagues, new_joined_league);
if(!valid_tag)
g_warning("xml_loadsave_league_start_element: unknown tag: %s; I'm in state %d\n",
element_name, state);
@ -112,6 +120,8 @@ xml_loadsave_league_end_element (GMarkupParseContext *context,
tag == TAG_LEAGUE_LAYER ||
tag == TAG_LEAGUE_ACTIVE ||
tag == TAG_LEAGUE_BREAK ||
tag == TAG_LEAGUE_JOINED_LEAGUE_SID ||
tag == TAG_LEAGUE_JOINED_LEAGUE_RR ||
tag == TAG_LEAGUE_TWO_MATCH_WEEK_START ||
tag == TAG_LEAGUE_TWO_MATCH_WEEK_END ||
tag == TAG_LEAGUE_AVERAGE_TALENT ||
@ -194,6 +204,15 @@ xml_loadsave_league_text (GMarkupParseContext *context,
new_league->active = int_value;
else if(state == TAG_LEAGUE_BREAK)
new_league->rr_break = int_value;
else if(state == TAG_LEAGUE_JOINED_LEAGUE_SID)
misc_string_assign(
&g_array_index(new_league->joined_leagues,
JoinedLeague,
new_league->joined_leagues->len - 1).sid, buf);
else if(state == TAG_LEAGUE_JOINED_LEAGUE_RR)
g_array_index(new_league->joined_leagues,
JoinedLeague,
new_league->joined_leagues->len - 1).rr = int_value;
else if(state == TAG_LEAGUE_TWO_MATCH_WEEK_START)
g_array_append_val(new_league->two_match_weeks[0], int_value);
else if(state == TAG_LEAGUE_TWO_MATCH_WEEK_END)
@ -289,6 +308,13 @@ xml_loadsave_league_write(const gchar *prefix, const League *league)
xml_write_int(fil, league->yellow_red, TAG_YELLOW_RED, I0);
xml_write_int(fil, league->active, TAG_LEAGUE_ACTIVE, I0);
xml_write_int(fil, league->rr_break, TAG_LEAGUE_BREAK, I0);
for(i = 0; i < league->joined_leagues->len; i++)
{
xml_write_string(fil, g_array_index(league->joined_leagues, JoinedLeague, i).sid, TAG_LEAGUE_JOINED_LEAGUE_SID, I0);
xml_write_int(fil, g_array_index(league->joined_leagues, JoinedLeague, i).rr, TAG_LEAGUE_JOINED_LEAGUE_RR, I0);
}
xml_write_float(fil, league->average_talent, TAG_LEAGUE_AVERAGE_TALENT, I0);
for(i=0;i<league->two_match_weeks[0]->len;i++)