bygfoot/src/league.c

533 lines
14 KiB
C
Raw Normal View History

2005-03-14 18:47:27 +01:00
#include "cup.h"
#include "free.h"
2004-12-23 13:58:39 +01:00
#include "league.h"
2005-06-15 21:13:35 +02:00
#include "main.h"
#include "maths.h"
2005-04-30 09:37:36 +02:00
#include "misc.h"
#include "option.h"
2005-04-13 15:01:59 +02:00
#include "player.h"
2005-04-29 21:48:02 +02:00
#include "stat.h"
2005-04-04 12:36:04 +02:00
#include "table.h"
#include "team.h"
2005-04-29 21:48:02 +02:00
#include "user.h"
#include "variables.h"
2004-12-23 13:58:39 +01:00
/**
Create a new league with some default values.
@return The league we created.
@see League
*/
League
2005-04-14 21:07:25 +02:00
league_new(gboolean new_id)
2004-12-23 13:58:39 +01:00
{
League new;
new.name = g_string_new("");
new.names_file = g_string_new(opt_str("string_opt_player_names_file"));
new.sid = g_string_new("");
2004-12-23 13:58:39 +01:00
new.short_name = g_string_new("");
new.symbol = g_string_new("");
2005-04-14 21:07:25 +02:00
new.id = (new_id) ? league_id_new : -1;
2005-05-24 20:31:07 +02:00
new.layer = -1;
2005-05-07 16:19:52 +02:00
new.average_skill = 7000;
new.prom_rel.prom_games_dest_sid = g_string_new("");
2005-04-13 15:01:59 +02:00
new.prom_rel.prom_games_loser_sid = g_string_new("");
2005-05-06 18:35:19 +02:00
new.prom_rel.prom_games_cup_sid = g_string_new("");
2005-04-13 15:01:59 +02:00
new.prom_rel.prom_games_number_of_advance = 1;
2004-12-23 13:58:39 +01:00
new.prom_rel.elements = g_array_new(FALSE, FALSE, sizeof(PromRelElement));
new.teams = g_array_new(FALSE, FALSE, sizeof(Team));
2005-01-09 21:21:22 +01:00
new.fixtures = g_array_new(FALSE, FALSE, sizeof(Fixture));
2004-12-23 13:58:39 +01:00
2005-04-04 12:36:04 +02:00
new.table = table_new();
2005-01-09 21:21:22 +01:00
new.table.clid = new.id;
2004-12-23 13:58:39 +01:00
new.first_week = new.week_gap = 1;
new.round_robins = 2;
2004-12-23 13:58:39 +01:00
new.yellow_red = 1000;
2005-04-30 15:57:58 +02:00
new.stats = stat_league_new(new.id);
2005-04-29 21:48:02 +02:00
2004-12-23 13:58:39 +01:00
return new;
}
/**
Create a new PromRelElement with default values.
@return The PromRelElement we created.
@see PromRelElement
*/
PromRelElement
prom_rel_element_new(void)
{
PromRelElement new;
new.ranks[0] = new.ranks[1] = 0;
new.dest_sid = g_string_new("");
new.type = PROM_REL_NONE;
2004-12-23 13:58:39 +01:00
return new;
}
2005-01-09 21:21:22 +01:00
/** Get the array index of the given league or cup id.
@param clid The id of the league or cup.
@return The index in the leagues or cups array. */
gint
league_cup_get_index_from_clid(gint clid)
{
gint i;
gint index = -1;
if(clid < ID_CUP_START)
{
for(i=0;i<ligs->len;i++)
if(lig(i).id == clid)
{
index = i;
break;
}
}
else
2005-05-06 18:35:19 +02:00
for(i=0;i<cps->len;i++)
if(cp(i).id == clid)
2005-01-09 21:21:22 +01:00
{
index = i;
break;
}
if(index == -1)
2005-06-17 14:57:05 +02:00
{
2005-04-04 12:36:04 +02:00
g_warning("league_cup_get_index_from_clid: couldn't find league or cup with id %d\n", clid);
2005-06-17 14:57:05 +02:00
main_exit_program(EXIT_POINTER_NOT_FOUND, NULL);
}
2005-01-09 21:21:22 +01:00
return index;
}
/** Return the league pointer belonging to the id.
@param clid The id we look for.
@return The league pointer or NULL if failed. */
League*
league_from_clid(gint clid)
{
gint i;
for(i=0;i<ligs->len;i++)
if(lig(i).id == clid)
return &lig(i);
g_warning("league_from_clid: didn't find league with id %d\n", clid);
2005-06-15 21:13:35 +02:00
2005-06-17 14:57:05 +02:00
main_exit_program(EXIT_POINTER_NOT_FOUND, NULL);
2005-06-15 21:13:35 +02:00
return NULL;
}
2005-03-14 18:47:27 +01:00
/** Return the id of the next league (or cup if we are
at the end of the leagues array).
@param clid The id of the current league or cup. */
gint
league_cup_get_next_clid(gint clid)
{
gint i, return_value = -1;
if(clid < ID_CUP_START)
{
for(i=0;i<ligs->len;i++)
if(lig(i).id == clid)
break;
if(i != ligs->len - 1)
return_value = lig(i + 1).id;
2005-04-25 21:39:43 +02:00
else if(acps->len > 0)
return_value = acp(0)->id;
2005-03-14 18:47:27 +01:00
else
2005-04-06 13:14:34 +02:00
return_value = lig(0).id;
2005-03-14 18:47:27 +01:00
}
else
{
2005-04-14 21:07:25 +02:00
for(i=0;i<acps->len;i++)
if(acp(i)->id == clid)
2005-04-13 15:01:59 +02:00
break;
2005-03-14 18:47:27 +01:00
2005-04-14 21:07:25 +02:00
if(i != acps->len - 1)
return_value = acp(i + 1)->id;
2005-03-14 18:47:27 +01:00
else
return_value = lig(0).id;
}
return return_value;
}
/** Return the id of the previous league or cup.
@param clid The id of the current league or cup. */
gint
league_cup_get_previous_clid(gint clid)
{
gint i, return_value = -1;
if(clid < ID_CUP_START)
{
for(i=ligs->len - 1;i>=0;i--)
if(lig(i).id == clid)
break;
if(i != 0)
return_value = lig(i - 1).id;
2005-04-14 21:07:25 +02:00
else if(acps->len > 0)
return_value = acp(acps->len - 1)->id;
2005-03-14 18:47:27 +01:00
else
2005-04-06 13:14:34 +02:00
return_value = lig(ligs->len - 1).id;
2005-03-14 18:47:27 +01:00
}
else
{
2005-04-14 21:07:25 +02:00
for(i=acps->len - 1;i>=0;i--)
if(acp(i)->id == clid)
2005-03-14 18:47:27 +01:00
break;
if(i != 0)
2005-04-14 21:07:25 +02:00
return_value = acp(i - 1)->id;
2005-03-14 18:47:27 +01:00
else
return_value = lig(ligs->len - 1).id;
}
return return_value;
}
/** Return the fixture coming after the specified week and round.
@param league The league the fixtures of which we examine.
@return A fixture pointer or NULL. */
Fixture*
league_cup_get_next_fixture(gint clid, gint week_number, gint week_round_number)
{
gint i;
2005-03-27 19:59:57 +02:00
GArray *fixtures = league_cup_get_fixtures(clid);
2005-03-14 18:47:27 +01:00
for(i=0;i<fixtures->len;i++)
if(g_array_index(fixtures, Fixture, i).week_number > week_number ||
(g_array_index(fixtures, Fixture, i).week_number == week_number &&
2005-04-14 21:07:25 +02:00
g_array_index(fixtures, Fixture, i).week_round_number >= week_round_number))
2005-03-14 18:47:27 +01:00
return &g_array_index(fixtures, Fixture, i);
return NULL;
}
/** Return the fixture coming just before the specified week and round.
@param league The league the fixtures of which we examine.
@return A fixture pointer or NULL. */
Fixture*
league_cup_get_previous_fixture(gint clid, gint week_number, gint week_round_number)
{
gint i;
2005-03-27 19:59:57 +02:00
GArray *fixtures = league_cup_get_fixtures(clid);
2005-03-14 18:47:27 +01:00
for(i=fixtures->len - 1;i>=0;i--)
if(g_array_index(fixtures, Fixture, i).week_number < week_number ||
(g_array_index(fixtures, Fixture, i).week_number == week_number &&
g_array_index(fixtures, Fixture, i).week_round_number < week_round_number))
return &g_array_index(fixtures, Fixture, i);
return NULL;
}
2005-03-16 21:48:25 +01:00
/** Return the average stadium capacity of cpu teams
in the specified league or cup. */
gint
league_cup_average_capacity(gint clid)
{
2005-05-09 19:06:11 +02:00
gint i, len;
2005-03-16 21:48:25 +01:00
gfloat sum = 0;
2005-05-09 19:06:11 +02:00
const GArray *teams = NULL;
const GPtrArray *teamsp = NULL;
2005-03-16 21:48:25 +01:00
2005-05-09 19:06:11 +02:00
if(clid < ID_CUP_START)
{
teams = (GArray*)league_cup_get_teams(clid);
len = teams->len;
for(i=0;i<teams->len;i++)
if(team_is_user(&g_array_index(teams, Team, i)) == -1)
sum += g_array_index(teams, Team, i).stadium.capacity;
}
else
{
teamsp = (GPtrArray*)league_cup_get_teams(clid);
len = teamsp->len;
for(i=0;i<teamsp->len;i++)
if(team_is_user((Team*)g_ptr_array_index(teamsp, i)) == -1)
sum += ((Team*)g_ptr_array_index(teamsp, i))->stadium.capacity;
}
return sum / (gfloat)len;
2005-03-16 21:48:25 +01:00
}
2005-04-13 15:01:59 +02:00
/** Get the index of the league with the specified string id. */
gint
league_index_from_sid(const gchar *sid)
{
gint i;
for(i=0;i<ligs->len;i++)
if(strcmp(lig(i).sid->str, sid) == 0)
return i;
g_warning("league_index_from_sid: no index found for sid '%s'.\n", sid);
2005-06-17 14:57:05 +02:00
main_exit_program(EXIT_INT_NOT_FOUND, NULL);
2005-06-16 08:56:12 +02:00
2005-04-13 15:01:59 +02:00
return -1;
}
/** Remove the team with the specified id from the teams
array without freeing the memory (used in promotion/relegation). */
void
league_remove_team_with_id(League *league, gint id)
{
gint i;
for(i=0;i<league->teams->len;i++)
if(g_array_index(league->teams, Team, i).id == id)
{
g_array_remove_index(league->teams, i);
return;
}
g_warning("league_remove_team_with_id: team with id %d in league %s not found\n",
id, league->name->str);
}
/** Add the teams to promote/relegate (from the prom_rel elements)
from the league to the array. */
2005-04-13 15:01:59 +02:00
void
league_get_team_movements_prom_rel(const League *league, GArray *team_movements)
2005-04-13 15:01:59 +02:00
{
2005-05-06 18:35:19 +02:00
gint i, j, k;
2005-04-13 15:01:59 +02:00
TeamMove new_move;
const GArray *elements = league->prom_rel.elements;
GPtrArray *dest_sids = NULL;
2005-04-13 15:01:59 +02:00
for(i=0;i<elements->len;i++)
{
dest_sids =
2005-04-30 09:37:36 +02:00
misc_separate_strings(g_array_index(elements, PromRelElement, i).dest_sid->str);
gint order[dest_sids->len];
k = 0;
math_generate_permutation(order, 0, dest_sids->len - 1);
2005-04-13 15:01:59 +02:00
for(j=g_array_index(elements, PromRelElement, i).ranks[0];
j<=g_array_index(elements, PromRelElement, i).ranks[1]; j++)
{
new_move.tm = *(g_array_index(league->table.elements, TableElement, j - 1).team);
2005-04-30 09:37:36 +02:00
new_move.league_idx =
league_index_from_sid(((GString*)g_ptr_array_index(dest_sids, order[k++ % dest_sids->len]))->str);
2005-06-22 17:07:34 +02:00
new_move.prom_rel_type = g_array_index(elements, PromRelElement, i).type;
2005-04-13 15:01:59 +02:00
g_array_append_val(team_movements, new_move);
2005-04-16 09:46:04 +02:00
if(team_is_user(g_array_index(league->table.elements, TableElement, j - 1).team) != -1)
{
if(g_array_index(elements, PromRelElement, i).type == PROM_REL_PROMOTION)
user_history_add(&usr(team_is_user(
g_array_index(league->table.elements, TableElement, j - 1).team)),
USER_HISTORY_PROMOTED, new_move.tm.id, lig(new_move.league_idx).id, -1, "");
else
user_history_add(&usr(team_is_user(
g_array_index(league->table.elements, TableElement, j - 1).team)),
USER_HISTORY_RELEGATED, new_move.tm.id, lig(new_move.league_idx).id, -1, "");
}
2005-04-13 15:01:59 +02:00
}
2005-04-30 09:37:36 +02:00
free_g_string_array(&dest_sids);
}
}
/** Add the team movements from the promotion games
to the array. */
void
league_get_team_movements_prom_games(const League *league, GArray *team_movements,
const GPtrArray *prom_games_teams, gboolean up)
{
gint i, k;
TeamMove new_move;
GPtrArray *dest_sids = (up) ?
misc_separate_strings(league->prom_rel.prom_games_dest_sid->str) :
misc_separate_strings(league->prom_rel.prom_games_loser_sid->str);
gint order[dest_sids->len];
gint start_idx = 0,
end_idx = league->prom_rel.prom_games_number_of_advance;
gint prom_type = PROM_REL_PROMOTION,
user_his_type = USER_HISTORY_PROMOTED;
if(!up)
{
start_idx = league->prom_rel.prom_games_number_of_advance;
end_idx = prom_games_teams->len;
prom_type = PROM_REL_RELEGATION;
user_his_type = USER_HISTORY_RELEGATED;
}
k = 0;
math_generate_permutation(order, 0, dest_sids->len - 1);
for(i=start_idx;i<end_idx;i++)
{
new_move.tm = *((Team*)g_ptr_array_index(prom_games_teams, i));
new_move.league_idx =
league_index_from_sid(((GString*)g_ptr_array_index(dest_sids, order[k++ % dest_sids->len]))->str);
new_move.prom_rel_type = prom_type;
g_array_append_val(team_movements, new_move);
if(team_is_user((Team*)g_ptr_array_index(prom_games_teams, i)) != -1)
user_history_add(&usr(team_is_user((Team*)g_ptr_array_index(prom_games_teams, i))),
user_his_type, new_move.tm.id, lig(new_move.league_idx).id, -1, "");
2005-04-13 15:01:59 +02:00
}
free_g_string_array(&dest_sids);
}
/** Add the teams to promote/relegate from the league to the array
and remove them from the leagues. */
void
league_get_team_movements(League *league, GArray *team_movements)
{
GPtrArray *prom_games_teams = NULL;
const Cup *prom_cup = NULL;
league_get_team_movements_prom_rel(league, team_movements);
2005-04-13 15:01:59 +02:00
2005-05-28 12:41:53 +02:00
if(query_league_has_prom_games(league))
2005-04-13 15:01:59 +02:00
{
2005-05-06 18:35:19 +02:00
prom_cup = cup_from_sid(league->prom_rel.prom_games_cup_sid->str);
if(prom_cup == NULL)
2005-04-13 15:01:59 +02:00
{
2005-05-06 18:35:19 +02:00
g_warning("league_get_team_movements: promotion games cup not found for league %s (cup sid %s).\n",
league->name->str, league->prom_rel.prom_games_cup_sid->str);
2005-04-13 15:01:59 +02:00
return;
}
2005-05-06 18:35:19 +02:00
prom_games_teams = cup_get_teams_sorted(prom_cup);
2005-04-16 09:46:04 +02:00
league_get_team_movements_prom_games(league, team_movements, prom_games_teams, TRUE);
2005-04-13 15:01:59 +02:00
if(strlen(league->prom_rel.prom_games_loser_sid->str) > 0)
league_get_team_movements_prom_games(league, team_movements,
prom_games_teams, FALSE);
2005-04-13 15:01:59 +02:00
g_ptr_array_free(prom_games_teams, TRUE);
}
2005-05-06 18:35:19 +02:00
2005-06-23 11:22:37 +02:00
g_array_sort_with_data(league->teams, team_compare_func,
GINT_TO_POINTER(TEAM_COMPARE_LEAGUE_RANK + 100));
2005-04-13 15:01:59 +02:00
}
/** Nullify league stuff at the beginning of a season. */
void
league_season_start(League *league)
{
gint i, j;
gint idx = league_index_from_sid(league->sid->str);
gboolean user_champ =
(team_is_user(
team_of_id(g_array_index(lig(0).table.elements, TableElement, 0).team_id)) != -1);
gfloat team_change_factor = 0;
2005-04-13 15:01:59 +02:00
for(i=0;i<league->table.elements->len;i++)
{
g_array_index(league->table.elements, TableElement, i).team =
&g_array_index(league->teams, Team, i);
g_array_index(league->table.elements, TableElement, i).team_id =
g_array_index(league->teams, Team, i).id;
2005-05-06 18:35:19 +02:00
g_array_index(league->table.elements, TableElement, i).old_rank = i;
2005-04-13 15:01:59 +02:00
for(j=0;j<TABLE_END;j++)
g_array_index(league->table.elements, TableElement, i).values[j] = 0;
}
for(i=0;i<league->teams->len;i++)
{
team_change_factor =
(team_is_user(&g_array_index(league->teams, Team, i)) == -1) *
math_rnd(const_float("float_season_end_team_change_lower") +
(user_champ && idx == 0) * const_float("float_season_end_user_champ_addition"),
const_float("float_season_end_team_change_upper") +
(user_champ && idx == 0) * const_float("float_season_end_user_champ_addition"));
2005-04-13 15:01:59 +02:00
for(j=0;j<g_array_index(league->teams, Team, i).players->len;j++)
player_season_start(
&g_array_index(g_array_index(league->teams, Team, i).players, Player, j), team_change_factor);
if(team_is_user(&g_array_index(league->teams, Team, i)) == -1)
team_update_cpu_structure(&g_array_index(league->teams, Team, i));
2005-05-11 22:17:24 +02:00
g_array_index(league->teams, Team, i).stadium.average_attendance =
g_array_index(league->teams, Team, i).stadium.games =
g_array_index(league->teams, Team, i).stadium.possible_attendance = 0;
}
2005-04-13 15:01:59 +02:00
}
/** Find out whether the team with specified rank in the league
would participate in promotion games were the season to end. */
gboolean
query_league_rank_in_prom_games(const League *league, gint rank)
{
2005-05-08 19:56:26 +02:00
gint i, j, k;
2005-05-06 18:35:19 +02:00
const Cup *cup = NULL;
2005-05-08 19:56:26 +02:00
const CupRound *cup_round = NULL;
2005-04-13 15:01:59 +02:00
for(i=0;i<ligs->len;i++)
2005-05-28 12:41:53 +02:00
if(query_league_has_prom_games((&lig(i))))
2005-04-13 15:01:59 +02:00
{
2005-05-06 18:35:19 +02:00
cup = cup_from_sid(lig(i).prom_rel.prom_games_cup_sid->str);
2005-05-08 19:56:26 +02:00
for(k=0;k<cup->rounds->len;k++)
2005-04-14 21:07:25 +02:00
{
2005-05-08 19:56:26 +02:00
cup_round = &g_array_index(cup->rounds, CupRound, k);
for(j=0;j<cup_round->choose_teams->len;j++)
{
if(strcmp(g_array_index(cup_round->choose_teams, CupChooseTeam, j).sid->str,
league->sid->str) == 0 &&
((rank >= g_array_index(cup_round->choose_teams,
CupChooseTeam, j).start_idx &&
rank <= g_array_index(cup_round->choose_teams,
CupChooseTeam, j).end_idx &&
g_array_index(cup_round->choose_teams,
CupChooseTeam, j).randomly) ||
(rank >= g_array_index(cup_round->choose_teams,
CupChooseTeam, j).start_idx &&
rank < g_array_index(cup_round->choose_teams,
CupChooseTeam, j).start_idx +
g_array_index(cup_round->choose_teams,
CupChooseTeam, j).number_of_teams &&
!g_array_index(cup_round->choose_teams,
CupChooseTeam, j).randomly)))
return TRUE;
}
2005-04-14 21:07:25 +02:00
}
2005-04-13 15:01:59 +02:00
}
return FALSE;
}
2005-04-24 16:19:57 +02:00
/** Find out whether there are/were league matches. */
gboolean
query_league_matches_in_week(const League *league, gint week_number)
{
gint i;
for(i=0;i<league->fixtures->len;i++)
if(g_array_index(league->fixtures, Fixture, i).week_number == week_number)
return TRUE;
return FALSE;
}