Best Python code snippet using hypothesis
team_draw_analysis.py
Source:team_draw_analysis.py  
1from ._data_organizer import _DataOrganizer, pd, plt2from .utils.validation import (3    seasons_arg_validation,4    teams_arg_validation,5    plot_type_arg_validation,6    draw_results_plot_arg_validation,7    draw_series_arg_validation8)9class TeamDrawAnalysis(_DataOrganizer):10    """TeamDrawAnalysis class provides and visualizes draw results performance for teams.11        'Attributes'12        ------------13            rawdata (pd.DataFrame): provided raw fixtures data.14            fixtures_data (pd.DataFrame): automatically cleaned and optimized data from raw data fixtures.15            seasons (list): calculated league seasons from 'fixtures data'.16            teams (list): league teams from 'fixtures data'.17            draw_score (float): total draw score.18    """19    def __init__(self, rawdata):20        super().__init__(rawdata)21    def __calculate_teams_no_draw_series(self, series_type):22        """Method to calculate no draw/draw series for teams. Based on 'fixtures_data'.23            Parameters24            ----------25            series_type (int): 0 - for no draw series, 1 - draw series.26            Returns27            ----------28            pd.DataFrame: concatenated no draw/draw series of matches for teams.29        """30        pd.options.mode.chained_assignment = None31        # data optimizing32        fixtures_data = self.fixtures_data.copy()33        fixtures_data = fixtures_data[34            ['fixture_date', 'league_season', 'teams_home_name', 'teams_away_name', 'match_result']]35        fixtures_data['fixture_date'] = pd.to_datetime(fixtures_data['fixture_date']).dt.strftime('%Y-%m-%d')36        fixtures_data.sort_values(by='fixture_date', inplace=True)37        teams_list = self.teams38        def calucate_series_for_team(_fixtures_data, _teams_list, _series_type):39            """Group and calculate no draw/draw series for teams.40            Parameters41            ----------42            fixtures_data (pd.DataFrame): optimized attribute 'fixtures_data'.43            teams_list (list): list of available 'fixtures_data' teams.44            series_type (int): 0 - for no draw series, 1 - draw series.45            Returns46            ----------47            list: list of pd.DataFrame with calculated draw/no draw series by teams.48            """49            _teams_series_to_concat_list = []50            # add auxiliary column for no draw/draw series51            if series_type == 0:52                fixtures_data['aux_result'] = fixtures_data['match_result'].apply(lambda x: 0 if x == 0 else 1)53            elif series_type == 1:54                fixtures_data['aux_result'] = fixtures_data['match_result'].apply(lambda x: 1 if x == 0 else 0)55            for team in teams_list:56                team_filter = fixtures_data[57                    (fixtures_data['teams_home_name'] == team) | (fixtures_data['teams_away_name'] == team)]58                team_filter['series_without_draw'] = team_filter.groupby(team_filter['aux_result'].eq(0).cumsum())[59                    'aux_result'].cumsum()60                team_filter['from_to_date'] = ''61                for a in range(0, len(team_filter)):62                    if team_filter.iloc[a, 6] != 0:63                        try:64                            if team_filter.iloc[a + 1, 6] == 0:65                                if a - team_filter.iloc[a, 6] < 0:66                                    team_filter.iloc[a, 7] = 'NoData' + '__' + str(team_filter.iloc[a + 1, 0])67                                else:68                                    team_filter.iloc[a, 7] = str(69                                        team_filter.iloc[a - team_filter.iloc[a, 6] + 1, 0]) + '__' + str(70                                        team_filter.iloc[a + 1, 0])71                        except IndexError:72                            if a + 1 == len(team_filter):73                                if a - team_filter.iloc[a, 6] < 0:74                                    team_filter.iloc[a, 7] = 'NoData__' + 'ToDate'75                                else:76                                    team_filter.iloc[a, 7] = str(77                                        team_filter.iloc[a - team_filter.iloc[a, 6] + 1, 0]) + '__ToDate'78                            else:79                                team_filter.iloc[a, 7] = 'NoData__' + str(80                                    team_filter.iloc[a - team_filter.iloc[a, 6], 0])81                team_second_filter = team_filter[team_filter['from_to_date'] > '']82                _team_series = pd.DataFrame(index=range(0, len(team_second_filter)),83                                            data={'team_name': team,84                                                  'league_season': team_second_filter['league_season'].to_list(),85                                                  'series_without_draw': team_second_filter[86                                                      'series_without_draw'].to_list(),87                                                  'from_to_date': team_second_filter['from_to_date'].to_list()})88                _team_series.sort_values(by='series_without_draw', ascending=False, inplace=True)89                _teams_series_to_concat_list.append(_team_series)90            return _teams_series_to_concat_list91        teams_series_to_concat_list = calucate_series_for_team(fixtures_data, teams_list, series_type)92        team_series = pd.concat(teams_series_to_concat_list, ignore_index=True)93        return team_series94    def __draw_results_data_filter(self, seasons):95        """Auxiliry method for 'draw_results_by_team_plot'. Filter attribute 'teams_draw_results_summarize' for plot.96        """97        teams_draw_results = TeamDrawAnalysis.teams_draw_results_summarize(self)98        if seasons == 'total':99            draw_results_filtered = teams_draw_results.iloc[:, -3:]100            draw_results_sorted = draw_results_filtered.sort_values(draw_results_filtered.columns[0], ascending=False)101            return draw_results_sorted102        elif isinstance(seasons, int):103            columns_to_filter = []104            for column in teams_draw_results.columns:105                if str(seasons) in column:106                    columns_to_filter.append(column)107            draw_results_filtered = teams_draw_results[columns_to_filter]108            draw_results_sorted = draw_results_filtered.sort_values(draw_results_filtered.columns[0], ascending=False)109            return draw_results_sorted110    def __team_draw_results_plot(self, _team_draw_results, plot_type, top, _seasons):111        """Auxiliry method for 'draw_results_by_team_plot' public method. Draw bar plot based on attribute112           'teams_draw_results_summarize'.113        Parameters114        ----------115        team_draw_results(pd.DataFrame): argument provided by public method - 'draw_results_by_team_plot'.116        plot_type (str): results number - 'rslts_num', percentage share of draw results - 'pcts'.117        seasons(str,int): provided and validated season.118        top (int): top (positive) or last (negative) of teams to ilustrate.119        Returns120        ----------121        matplotlib.pyplot.bar: bar plot number/percentage share of draw results.122        """123        plot_type_arg_validation(plot_type)124        #125        def draw_results_number_plot(_team_draw_results, _seasons, ytick_step):126            """Plot bar chart for plot_type = 'rslts_num'.127            """128            _draw_results_number_plot = _team_draw_results[129                [_team_draw_results.columns[0], 'total_matches_aux_col']].plot(130                kind='bar', color=self._graph_colors[0::2], alpha=0.8, stacked=True, yticks=ytick_setter,131                rot=80,132                title=f"Number of draws to the total results - {_seasons}")133            pcts_line = _team_draw_results[_team_draw_results.columns[-1]].plot(secondary_y=True, rot=80,134                                                                                color='tab:olive', legend=True)135            _draw_results_number_plot.legend(['draw_results_num', 'total_matches_num'], loc='center left',136                                             bbox_to_anchor=(1.07, 0.93))137            pcts_line.legend(loc='center left', bbox_to_anchor=(1.07, 0.844))138            plt.show()139        def draw_pcts_to_total_plot(_team_draw_results, _seasons, ytick_step):140            """Plot bar chart for plot_type='pcts'141            """142            _draw_pcts_to_total_plot = _team_draw_results[_team_draw_results.columns[-1]] \143                .plot(kind='bar',144                      yticks=ytick_setter, rot=80,145                      ylabel='%',146                      color=_DataOrganizer._graph_colors[2],147                      legend=True,148                      title=f"Draws percentage share to the total results - {_seasons}")149            plt.show()150        if plot_type == 'count':151            ytick_setter = self._yticks_plot_auto_setter(_team_draw_results[_team_draw_results.columns[1]] + 5)152            _team_draw_results.insert(2, column='total_matches_aux_col',153                                      value=_team_draw_results[_team_draw_results.columns[1]] - _team_draw_results[154                                          _team_draw_results.columns[0]])155            if top > 0:156                _team_draw_results = _team_draw_results.head(top)157                return draw_results_number_plot(_team_draw_results, _seasons, ytick_setter)158            else:159                _team_draw_results = _team_draw_results.tail(abs(top))160                return draw_results_number_plot(_team_draw_results, _seasons, ytick_setter)161        elif plot_type == 'pcts':162            ytick_setter = self._yticks_plot_auto_setter(163                _team_draw_results[_team_draw_results.columns[-1]] + 5)164            _team_draw_results = _team_draw_results.sort_values(_team_draw_results.columns[-1], ascending=False)165            if top > 0:166                _team_draw_results = _team_draw_results.head(top)167                return draw_pcts_to_total_plot(_team_draw_results, _seasons, ytick_setter)168            else:169                _team_draw_results = _team_draw_results.tail(abs(top))170                return draw_pcts_to_total_plot(_team_draw_results, _seasons, ytick_setter)171    def __calculate_draw_performance(self):172        """Calculate draw results performance for all teams and seasons by merging:173            - draws percentage share (TeamDrawAnalysis.teams_draw_results_summarize())174            - team table position (self.league_table())175            - no draw series max/mean per season/total (self.teams_draw_series())176            - draw series max/mean per season/total (self.teams_draw_series())177            Returns178            ----------179            pandas.DataFrame: draw results performance.180        """181        # 1. Filter columns from 'teams_draw_results_summarize' attribute182        # - columns to filter183        draw_pcts_col_list = []184        teams_draw_results_summarize = TeamDrawAnalysis.teams_draw_results_summarize(self)185        # - add draw pcts results per seasons to draw_pcts_col_list186        for season in self._seasons:187            for col in teams_draw_results_summarize.columns.to_list():188                if 'pcts_' + str(season) in col and 'match_num' not in col:189                    draw_pcts_col_list.append(col)190                if len(self.seasons) > 1:191                    if season == self.seasons[-1] and 'pcts_total' in col:192                        draw_pcts_col_list.append(col)193        # - filter194        draw_results_performance = teams_draw_results_summarize.copy()195        draw_results_performance = draw_results_performance[draw_pcts_col_list]196        # 2. Teams position in table from197        table_pos_col_list = []198        for season in self._seasons:199            table_position = self.league_table(season)['Team'].to_frame()200            table_position['table_pos_' + str(season)] = table_position.index201            table_position.set_index('Team', inplace=True)202            table_pos_col_list.append(table_position.columns[0])203            draw_results_performance = draw_results_performance.merge(table_position, how='left', left_index=True,204                                                                      right_index=True)205        # 3. New columns order - teams table positions and draw pcts results206        new_columns_order_list = []207        for col in zip(table_pos_col_list, draw_pcts_col_list):208            new_columns_order_list.append(col[0])209            new_columns_order_list.append(col[1])210        # add total draw pcts results column if len(seasons) > 1211        if len(self._seasons) > 1:212            new_columns_order_list.append(draw_pcts_col_list[-1])213        # draw_results_performance new column order if len(seasons) > 1214        draw_results_performance = draw_results_performance[new_columns_order_list]215        # 5. Draw/no draw series216        def merge_draw_performance_with_draw_series(_draw_results_performance, series_type):217            """Calculate max/mean, no draw/draw series for teams and merge with 'draw_results_performance'218            Parameters219            ----------220            draw_results_performance (padnas.DataFrame): organized DF with teams positions and draws percentage share221            series_type (int): 0 - series without draw, 1 - draw series.222            Returns223            ----------224            pandas.DataFrame: merged draw_results_performance with draw/no draws series.225            """226            no_draw_series_dataframe_list = []227            # mapper to change the column name for draw/ no draw series228            series_type_mapper = {0: 'no_draw_', 1: 'draw_'}229            # no draw/draw series - max, mean per seasons230            for _season in self._seasons:231                no_draw_series_max_season = self.teams_draw_series(seasons=_season,232                                                                   series_type=series_type,233                                                                   func='max').iloc[:, 1].to_frame()234                no_draw_series_max_season.rename(235                    {no_draw_series_max_season.columns[0]: series_type_mapper[series_type] + 'max_' + str(_season)},236                    axis=1, inplace=True)237                no_draw_series_mean_season = self.teams_draw_series(seasons=_season,238                                                                    series_type=series_type,239                                                                    func='mean').iloc[:, 0].to_frame()240                no_draw_series_mean_season.rename(241                    {no_draw_series_mean_season.columns[0]: series_type_mapper[series_type] + 'mean_' + str(_season)},242                    axis=1, inplace=True)243                no_draw_series_dataframe_list.append(no_draw_series_max_season)244                no_draw_series_dataframe_list.append(no_draw_series_mean_season)245            # no draw/draw total from data246            if len(self._seasons) > 1:247                no_draw_series_max_total = self.teams_draw_series(seasons='all', series_type=series_type,248                                                                  func='max').iloc[:, 1].to_frame()249                no_draw_series_max_total.rename(250                    {no_draw_series_max_total.columns[0]: series_type_mapper[series_type] + 'max_total'}, axis=1,251                    inplace=True)252                no_draw_series_mean_total = self.teams_draw_series(seasons='all', series_type=series_type,253                                                                   func='mean').iloc[:, 0].to_frame()254                no_draw_series_mean_total.rename(255                    {no_draw_series_mean_total.columns[0]: series_type_mapper[series_type] + 'mean_total'}, axis=1,256                    inplace=True)257                no_draw_series_dataframe_list.append(no_draw_series_max_total)258                no_draw_series_dataframe_list.append(no_draw_series_mean_total)259            # merge no draw/draw series with 'draw_results_performance'260            for df in no_draw_series_dataframe_list:261                _draw_results_performance = _draw_results_performance.merge(df, how='left', left_index=True,262                                                                            right_index=True)263            return _draw_results_performance264        # 6. Merge draw_results_performance with draw/no draw series265        draw_results_performance = merge_draw_performance_with_draw_series(draw_results_performance, series_type=0)266        draw_results_performance = merge_draw_performance_with_draw_series(draw_results_performance, series_type=1)267        # 7.Fill Nan values and change columns type:268        draw_results_performance.fillna(0, inplace=True)269        for col in draw_results_performance.columns:270            if 'table_pos' in col or 'max' in col:271                draw_results_performance[col] = draw_results_performance[col].astype('int64')272        # 8. Goals performance273        teams_goals_performance_season = TeamDrawAnalysis.teams_goals_performance(self, seasons='all', teams='all')274        draw_results_performance = draw_results_performance.merge(teams_goals_performance_season, how='left',275                                                                  left_index=True, right_index=True)276        return draw_results_performance277    def __transpose_draw_performance_table(self, draw_performance_filtered_teams, seasons):278        """Auxiliary method for draw_results_performance_filter.279           Transpose table to multiindex teams and seasons.280            Parameters281            ----------282            draw_performance_filtered_teams(pandas.DataFrame): filtered draw performance table.283            Returns284            ----------285            pandas.DataFrame: transposed table.286        """287        seasons_list = []288        if seasons == 'all':289            seasons_list = self._seasons290        elif isinstance(seasons, int):291            seasons_list = [seasons]292        else:293            seasons_list = seasons294        # df list to further concatenation295        df_list = []296        # cerate df for seasons with unified columns297        for season in seasons_list:298            # columns for particular season299            columns_list = []300            # new unified columns names301            new_columns_name = []302            for column in draw_performance_filtered_teams.columns:303                if str(season) in column:304                    columns_list.append(column)305                    new_columns_name.append(column[0:column.rfind('_')])306            df_filtered = draw_performance_filtered_teams[columns_list]307            df_filtered.columns = new_columns_name308            # add multi column with season number309            df_filtered = pd.concat([df_filtered], axis=1, keys=[str(season)])310            df_list.append(df_filtered)311            # concatenation and transpose312        df_concat = pd.concat(df_list, axis=1)313        transposed = df_concat.stack(level=0)314        transposed.index.set_names(['team_name', 'league_season'], inplace=True)315        transposed = transposed[316            ['table_pos', 'draws_pcts', 'no_draw_max', 'no_draw_mean', 'draw_max', 'draw_mean', 'goals_mean',317             'goals_diff']]318        # drop indexesr with 0 values319        index_with_no_data = transposed[transposed[transposed.columns] == 0].dropna().index320        transposed.drop(index_with_no_data, inplace=True)321        return transposed322    def __draw_results_seasons_filter(self, seasons):323        draw_performance = TeamDrawAnalysis.__calculate_draw_performance(self)324        columns_to_filter = []325        draw_performance_filtered = None326        if len(self._seasons) == 1:327            for column in draw_performance.columns:328                if str(*self._seasons) in column:329                    columns_to_filter.append(column)330            draw_performance_filtered = draw_performance[columns_to_filter]331            draw_performance_filtered = draw_performance_filtered[332                draw_performance_filtered[draw_performance_filtered.columns[0]] > 0]333        elif isinstance(seasons, list):334            for season in seasons:335                for column in draw_performance.columns:336                    if str(season) in column:337                        columns_to_filter.append(column)338            draw_performance_filtered = draw_performance[columns_to_filter]339        elif isinstance(seasons, int):340            for column in draw_performance.columns:341                if str(seasons) in column:342                    columns_to_filter.append(column)343            draw_performance_filtered = draw_performance[columns_to_filter]344            draw_performance_filtered = draw_performance_filtered[345                draw_performance_filtered[draw_performance_filtered.columns[0]] > 0]346        else:347            draw_performance_filtered = draw_performance348        return draw_performance_filtered349    def teams_draw_results_summarize(self):350        """Group 'fixtures_data' to calculate number of draws, number of total matches and percentage share of draw351           results by teams.352            Returns353            ----------354                pd.DataFame: teams_draw_results_summarize.355        """356        def team_draw_results_count(_fixtures_data, _season):357            # group and count 0,1,2 results by team358            teams_home_rslts = \359                _fixtures_data.groupby(by=['league_season', 'teams_home_name', 'match_result']).agg('count')[360                    'fixture_id']361            teams_away_rslts = \362                _fixtures_data.groupby(by=['league_season', 'teams_away_name', 'match_result']).agg('count')[363                    'fixture_id']364            # combine teams_home_rslts and teams_away_rslts365            teams_results = teams_home_rslts.append(teams_away_rslts)366            # group and agg sum teams_home_rslts and teams_away_rslts367            teams_results_total = teams_results.groupby(by=['teams_home_name', 'match_result']).agg('sum')368            teams_results_total.index.set_names(names=['team_name', 'match_result'], inplace=True)369            # draw count processing370            team_draw_counted = teams_results_total.unstack()[0].to_frame()371            team_draw_counted.columns = ['draws_' + str(_season)]372            draws_number = team_draw_counted[team_draw_counted.columns[0]]373            # total matches count374            teams_total_matches = teams_results_total.groupby('team_name').agg('sum')375            # combine and calculate percentage share of draws376            if isinstance(_season, int):377                team_draw_counted['match_num_' + str(_season)] = teams_total_matches378                total_matches_number = team_draw_counted[team_draw_counted.columns[1]]379                team_draw_counted['draws_pcts_' + str(_season) + '(%)'] = round(380                    draws_number / total_matches_number * 100, 2)381            else:382                team_draw_counted['match_num_' + str(_season)] = teams_total_matches383                total_matches_number = team_draw_counted[team_draw_counted.columns[1]]384                team_draw_counted['draws_pcts_' + str(_season) + '(%)'] = round(385                    draws_number / total_matches_number * 100, 2)386            return team_draw_counted387        fixtures_data = self._fixtures_data.copy()388        seasons_list = self._seasons389        teams_draw_results_merged = pd.DataFrame()390        for season in seasons_list:391            fixtures_data_filtered = fixtures_data[fixtures_data['league_season'] == season]392            teams_draw_counted = team_draw_results_count(fixtures_data_filtered, season)393            if teams_draw_results_merged.empty:394                teams_draw_results_merged = teams_draw_results_merged.append(teams_draw_counted)395            else:396                teams_draw_results_merged = teams_draw_results_merged.merge(teams_draw_counted, left_index=True,397                                                                            right_index=True, how='outer')398        if len(seasons_list) > 1:399            teams_draw_total = team_draw_results_count(fixtures_data, 'total')400            teams_draw_results_merged = teams_draw_results_merged.merge(teams_draw_total, left_index=True,401                                                                        right_index=True, how='outer')402            teams_draw_results_merged.fillna(value=0, inplace=True)403        else:404            teams_draw_results_merged.fillna(value=0, inplace=True)405        return teams_draw_results_merged406    def draw_results_by_team_plot(self, plot_type='count', seasons='total', top=15):407        """Bar plot for draw results by team.408            Parameters409            ----------410            plot_type (str): type of bar plot - 'count' or 'pcts'.411            seasons(str,int): league season to plot. Deafult - 'total' data.412            top (int): top (positive) or last (negative) of teams to ilustrate.413            Raises414            ----------415                TypeError: Seasons argument must be int or str type.416                ValueError: Season does not exist.417                ValueError: Incorrect string value. Seasons must be int or 'total' for total data calculation.418                ValueError: Incorrect string value. The plot_type argument must be named 'rslts_num' or 'pcts'.419                TypeError: The 'plot_type' argument must be str type.420                TypeError: The 'top' argument must be int type.421            Returns422            ----------423            matplotlib.pyplot.bar: bar plot number/percentage share of draw results by team.424        """425        draw_results_plot_arg_validation(self, seasons, plot_type, top)426        team_draw_results = TeamDrawAnalysis.__draw_results_data_filter(self, seasons)427        TeamDrawAnalysis.__team_draw_results_plot(self, team_draw_results, plot_type, top, seasons)428    def teams_draw_series(self, series_type=0, seasons='all', teams='all', func='all'):429        """Calculate no draw/ draw results series for teams.430            Parameters431            ----------432            series_type (int): 0 - series without draw, 1 - draw series.433            seasons (int or list): Default - 'all' leauge seasons. Int or list of ints of league seasons for request.434            teams (str or list): Default 'all' - teams series, 'str' name for single team or list(str) of team names for435                                 request.436            func (str): Default 'all' - all teams series, 'max' - the longest series, 'mean' - average value of series.437            Raises438            ----------439                TypeError: 'series_type' argument must be int.440                ValueError: the value of 'series_type' argument must be 0 or 1.441                TypeError: 'seasons' argument must be integer, list of integers or 'all' string for all seasons.442                ValueError: Season does not exist.443                ValueError: one or more of seasons do not exists.444                ValueError: incorrect string value. 'Seasons' must be int, list of ints, 'all' for all seasons.445                TypeError: 'teams' argument must be string, list of strings.446                ValueError: team does not exist.447                ValueError: one or more of teams do not exists.448                TypeError: 'func' argument must be string type.449                ValueError: 'func' argument must be 'all', 'max' or 'mean'.450            Returns451            ----------452                pandas.DataFrame: filtered no draw/draw series for teams.453        """454        # arguments validation455        draw_series_arg_validation(self, series_type, seasons, teams, func)456        # 0 - no draw series, 1 - draw series457        if series_type == 0:458            draw_series = TeamDrawAnalysis.__calculate_teams_no_draw_series(self, series_type=0)459        else:460            draw_series = TeamDrawAnalysis.__calculate_teams_no_draw_series(self, series_type=1)461        # seasons filter462        if seasons == 'all':463            pass464        elif isinstance(seasons, list):465            draw_series = draw_series[draw_series['league_season'].isin(seasons)]466        else:467            draw_series = draw_series[draw_series['league_season'] == seasons]468        # teams filter469        if teams == 'all':470            pass471        elif isinstance(teams, list):472            draw_series = draw_series[draw_series['team_name'].isin(teams)]473        else:474            draw_series = draw_series[draw_series['team_name'] == teams]475        # func - 'all', 'max', 'mean'476        if func == 'max':477            max_rows = draw_series.groupby('team_name')['series_without_draw'].idxmax(axis=0).to_list()478            draw_series = draw_series.loc[max_rows]479        elif func == 'mean':480            draw_series = draw_series.groupby('team_name', as_index=False)['series_without_draw'].mean()481            draw_series['series_without_draw'] = round(draw_series['series_without_draw'], 2)482        draw_series.set_index('team_name', inplace=True)483        if series_type == 0:484            return draw_series485        elif series_type == 1:486            draw_series.rename({'series_without_draw': 'draw_series'}, axis=1, inplace=True)487            return draw_series488    def draw_results_performance(self, seasons='all', teams='all', transpose=False):489        """Calculate draw results performance.490            Parameters491            ----------492            seasons (int or list): Default - 'all' leauge seasons. Int or list of ints of league seasons for request.493            teams (str or list): Default 'all' - teams series, 'str' name for single team or list(str) of team names for494                                 request.495            transpose (bool): True to transpose table. Deafult = False.496            Raises497            ----------498                TypeError: 'seasons' argument must be integer, list of integers or 'all' string for all seasons.499                ValueError: Season does not exist.500                ValueError: one or more of seasons do not exists.501                ValueError: incorrect string value. 'Seasons' must be int, list of ints, 'all' for all seasons.502                TypeError: 'teams' argument must be string, list of strings.503                ValueError: team does not exist.504                ValueError: one or more of teams do not exists.505                TypeError: 'transpose' argument must be bool.506            Returns507            ----------508            pandas.DataFrame: filtered attribute draw_results_performance509        """510        # arg validation:511        seasons_arg_validation(self, seasons)512        teams_arg_validation(self, teams)513        if not isinstance(transpose, bool):514            raise TypeError(f"The 'transpose' argument must be bool, not {type(transpose).__name__} type.")515        draw_performance_filtered = self.__draw_results_seasons_filter(seasons)516        # teams filter517        if teams == 'all':518            draw_performance_filtered_teams = draw_performance_filtered519        elif isinstance(teams, str):520            draw_performance_filtered_teams = draw_performance_filtered.loc[teams].to_frame().transpose()521        else:522            draw_performance_filtered_teams = draw_performance_filtered.loc[teams]523        # transpose table524        if transpose is True:525            draw_performance_transposed = self.__transpose_draw_performance_table(draw_performance_filtered_teams,526                                                                                  seasons)527            return draw_performance_transposed528        else:529            return draw_performance_filtered_teams530    def teams_correct_scores(self, seasons='all', teams='all'):531        """Calculate counted of teams correct scores by seasons.532            Parameters533            ----------534            seasons (int or list): Default - 'all' leauge seasons. Int or list of ints of league seasons for request.535            teams (str or list): Default 'all' - teams series, 'str' name for single team or list(str) of team names for536                                 request.537            Raises538            ----------539                TypeError: 'seasons' argument must be integer, list of integers or 'all' string for all seasons.540                ValueError: Season does not exist.541                ValueError: one or more of seasons do not exists.542                ValueError: incorrect string value. 'Seasons' must be int, list of ints, 'all' for all seasons.543                TypeError: 'teams' argument must be string, list of strings.544                ValueError: team does not exist.545                ValueError: one or more of teams do not exists.546            Returns547            ----------548            pandas.DataFrame: counted correct scores by teams.549        """550        # arg validation and seasons, teams filter551        fixtures_data = self._fixtures_data.copy()552        fixtures_data_filtered_seasons = self._seasons_filter(fixtures_data, seasons)553        fixtures_data_filtered_teams = self._teams_filter(fixtures_data_filtered_seasons, teams)554        # teams home correct scores555        home_scores = \556            fixtures_data_filtered_teams.groupby(['teams_home_name', 'league_season', 'fulltime_match_result']).agg(557                'count')['fixture_id'].to_frame()558        home_scores.rename(columns={'fixture_id': 'home_scores'}, inplace=True)559        # teams away correct scores560        away_scores = \561            fixtures_data_filtered_teams.groupby(['teams_away_name', 'league_season', 'fulltime_match_result']).agg(562                'count')['fixture_id'].to_frame()563        # merge564        teams_coorect_scores = home_scores.copy()565        teams_coorect_scores['away_scores'] = away_scores['fixture_id']566        # drop index == 0567        index_with_no_data = teams_coorect_scores[568            teams_coorect_scores[teams_coorect_scores.columns] == 0].dropna().index569        teams_coorect_scores.drop(index_with_no_data, inplace=True)570        # detailed team filter571        if isinstance(teams, str) and not teams == 'all':572            teams_coorect_scores = teams_coorect_scores.loc[teams]573        return teams_coorect_scores574    def standings_draws(self):575        """Calculate compilation of positions in table and draws results.576            Returns577            ---------578            pd.DataFrame: league table with positions and counted draws by seasons.579        """580        df_list = []581        for season in self._seasons:582            df_list.append(self.league_table(season=season)['D'])583        draws_table = pd.DataFrame(index=df_list[0].index,584                                   data={str(season): df for df, season in zip(df_list, self._seasons)})585        return draws_table586    def teams_goals_performance(self, seasons='all', teams='all'):587        """Calculate goals mean per match and total goals difference for season.588            Parameters589            ----------590            seasons (int or list): Default - 'all' leauge seasons. Int or list of ints of league seasons for request.591            teams (str or list): Default 'all' - teams series, 'str' name for single team or list(str) of team names for592                                request.593            Raises594            ----------595                TypeError: 'seasons' argument must be integer, list of integers or 'all' string for all seasons.596                ValueError: Season does not exist.597                ValueError: one or more of seasons do not exists.598                ValueError: incorrect string value. 'Seasons' must be int, list of ints, 'all' for all seasons.599                TypeError: 'teams' argument must be string, list of strings.600                ValueError: team does not exist.601                ValueError: one or more of teams do not exists.602            Returns603            ----------604            pandas.DataFrame: teams goals performance.605        """606        # arg validation607        seasons_arg_validation(self, seasons)608        teams_arg_validation(self, teams)609        def teams_goals_mean_and_diff(_season):610            """Calculate goals mean per match and total goals difference for season.611            """612            season_league_table = TeamDrawAnalysis.league_table(self, season=_season)613            season_league_table['goals_mean_' + str(_season)] = round(614                season_league_table.apply(lambda x: (x['GF'] + x['GA']) / x['MP'], 1), 2)615            season_league_table.rename(columns={'GD': 'goals_diff_' + str(_season)}, inplace=True)616            teams_goals = season_league_table[617                ['Team', 'goals_mean_' + str(_season), 'goals_diff_' + str(_season)]]618            teams_goals.set_index('Team', drop=True, inplace=True)619            return teams_goals620        # seasons filter621        seasons_list = []622        if len(self._seasons) > 1:623            if seasons == 'all':624                seasons_list = self._seasons625            else:626                seasons_list = seasons627        team_goals_performance = pd.DataFrame()628        if len(self._seasons) > 1:629            teams_goals_perf_list = []630            team_goals_performance = pd.DataFrame(index=self._teams)631            if seasons == 'all' or isinstance(seasons, list):632                for season in seasons_list:633                    teams_goals_perf_season = teams_goals_mean_and_diff(season)634                    teams_goals_perf_list.append(teams_goals_perf_season)635                for df in teams_goals_perf_list:636                    team_goals_performance = team_goals_performance.merge(df, how='left', left_index=True,637                                                                          right_index=True)638            elif isinstance(seasons, int):639                team_goals_performance = teams_goals_mean_and_diff(seasons)640        elif len(self._seasons) == 1:641            team_goals_performance = teams_goals_mean_and_diff(self._seasons[0])642        # columns type643        team_goals_performance.fillna(value=0, inplace=True)644        for col in team_goals_performance.columns:645            if 'diff' in col:646                team_goals_performance[col] = team_goals_performance[col].astype('int')647        # team filter648        if teams == 'all':649            return team_goals_performance650        else:651            team_goals_performance_filtered = team_goals_performance.loc[teams]...test_imagedraw.py
Source:test_imagedraw.py  
...404            thresh=30)405        # Assert406        self.assert_image_equal(407            im, Image.open("Tests/images/imagedraw_floodfill2.png"))408    def create_base_image_draw(self, size,409                               mode=DEFAULT_MODE,410                               background1=WHITE,411                               background2=GRAY):412        img = Image.new(mode, size, background1)413        for x in range(0, size[0]):414            for y in range(0, size[1]):415                if (x + y) % 2 == 0:416                    img.putpixel((x, y), background2)417        return img, ImageDraw.Draw(img)418    def test_square(self):419        expected = Image.open(os.path.join(IMAGES_PATH, 'square.png'))420        expected.load()421        img, draw = self.create_base_image_draw((10, 10))422        draw.polygon([(2, 2), (2, 7), (7, 7), (7, 2)], BLACK)423        self.assert_image_equal(img, expected,424                                'square as normal polygon failed')425        img, draw = self.create_base_image_draw((10, 10))426        draw.polygon([(7, 7), (7, 2), (2, 2), (2, 7)], BLACK)427        self.assert_image_equal(img, expected,428                                'square as inverted polygon failed')429        img, draw = self.create_base_image_draw((10, 10))430        draw.rectangle((2, 2, 7, 7), BLACK)431        self.assert_image_equal(img, expected,432                                'square as normal rectangle failed')433        img, draw = self.create_base_image_draw((10, 10))434        draw.rectangle((7, 7, 2, 2), BLACK)435        self.assert_image_equal(436            img, expected, 'square as inverted rectangle failed')437    def test_triangle_right(self):438        expected = Image.open(os.path.join(IMAGES_PATH, 'triangle_right.png'))439        expected.load()440        img, draw = self.create_base_image_draw((20, 20))441        draw.polygon([(3, 5), (17, 5), (10, 12)], BLACK)442        self.assert_image_equal(img, expected, 'triangle right failed')443    def test_line_horizontal(self):444        expected = Image.open(os.path.join(IMAGES_PATH,445                              'line_horizontal_w2px_normal.png'))446        expected.load()447        img, draw = self.create_base_image_draw((20, 20))448        draw.line((5, 5, 14, 5), BLACK, 2)449        self.assert_image_equal(450            img, expected, 'line straight horizontal normal 2px wide failed')451        expected = Image.open(os.path.join(IMAGES_PATH,452                              'line_horizontal_w2px_inverted.png'))453        expected.load()454        img, draw = self.create_base_image_draw((20, 20))455        draw.line((14, 5, 5, 5), BLACK, 2)456        self.assert_image_equal(457            img, expected, 'line straight horizontal inverted 2px wide failed')458        expected = Image.open(os.path.join(IMAGES_PATH,459                              'line_horizontal_w3px.png'))460        expected.load()461        img, draw = self.create_base_image_draw((20, 20))462        draw.line((5, 5, 14, 5), BLACK, 3)463        self.assert_image_equal(464            img, expected, 'line straight horizontal normal 3px wide failed')465        img, draw = self.create_base_image_draw((20, 20))466        draw.line((14, 5, 5, 5), BLACK, 3)467        self.assert_image_equal(468            img, expected, 'line straight horizontal inverted 3px wide failed')469        expected = Image.open(os.path.join(IMAGES_PATH,470                              'line_horizontal_w101px.png'))471        expected.load()472        img, draw = self.create_base_image_draw((200, 110))473        draw.line((5, 55, 195, 55), BLACK, 101)474        self.assert_image_equal(475            img, expected, 'line straight horizontal 101px wide failed')476    def test_line_h_s1_w2(self):477        self.skipTest('failing')478        expected = Image.open(os.path.join(IMAGES_PATH,479                              'line_horizontal_slope1px_w2px.png'))480        expected.load()481        img, draw = self.create_base_image_draw((20, 20))482        draw.line((5, 5, 14, 6), BLACK, 2)483        self.assert_image_equal(484            img, expected, 'line horizontal 1px slope 2px wide failed')485    def test_line_vertical(self):486        expected = Image.open(os.path.join(IMAGES_PATH,487                              'line_vertical_w2px_normal.png'))488        expected.load()489        img, draw = self.create_base_image_draw((20, 20))490        draw.line((5, 5, 5, 14), BLACK, 2)491        self.assert_image_equal(492            img, expected, 'line straight vertical normal 2px wide failed')493        expected = Image.open(os.path.join(IMAGES_PATH,494                              'line_vertical_w2px_inverted.png'))495        expected.load()496        img, draw = self.create_base_image_draw((20, 20))497        draw.line((5, 14, 5, 5), BLACK, 2)498        self.assert_image_equal(499            img, expected, 'line straight vertical inverted 2px wide failed')500        expected = Image.open(os.path.join(IMAGES_PATH,501                              'line_vertical_w3px.png'))502        expected.load()503        img, draw = self.create_base_image_draw((20, 20))504        draw.line((5, 5, 5, 14), BLACK, 3)505        self.assert_image_equal(506            img, expected, 'line straight vertical normal 3px wide failed')507        img, draw = self.create_base_image_draw((20, 20))508        draw.line((5, 14, 5, 5), BLACK, 3)509        self.assert_image_equal(510            img, expected, 'line straight vertical inverted 3px wide failed')511        expected = Image.open(os.path.join(IMAGES_PATH,512                              'line_vertical_w101px.png'))513        expected.load()514        img, draw = self.create_base_image_draw((110, 200))515        draw.line((55, 5, 55, 195), BLACK, 101)516        self.assert_image_equal(img, expected,517                                'line straight vertical 101px wide failed')518        expected = Image.open(os.path.join(IMAGES_PATH,519                              'line_vertical_slope1px_w2px.png'))520        expected.load()521        img, draw = self.create_base_image_draw((20, 20))522        draw.line((5, 5, 6, 14), BLACK, 2)523        self.assert_image_equal(img, expected,524                                'line vertical 1px slope 2px wide failed')525    def test_line_oblique_45(self):526        expected = Image.open(os.path.join(IMAGES_PATH,527                              'line_oblique_45_w3px_a.png'))528        expected.load()529        img, draw = self.create_base_image_draw((20, 20))530        draw.line((5, 5, 14, 14), BLACK, 3)531        self.assert_image_equal(img, expected,532                                'line oblique 45 normal 3px wide A failed')533        img, draw = self.create_base_image_draw((20, 20))534        draw.line((14, 14, 5, 5), BLACK, 3)535        self.assert_image_equal(img, expected,536                                'line oblique 45 inverted 3px wide A failed')537        expected = Image.open(os.path.join(IMAGES_PATH,538                              'line_oblique_45_w3px_b.png'))539        expected.load()540        img, draw = self.create_base_image_draw((20, 20))541        draw.line((14, 5, 5, 14), BLACK, 3)542        self.assert_image_equal(img, expected,543                                'line oblique 45 normal 3px wide B failed')544        img, draw = self.create_base_image_draw((20, 20))545        draw.line((5, 14, 14, 5), BLACK, 3)546        self.assert_image_equal(img, expected,547                                'line oblique 45 inverted 3px wide B failed')548    def test_wide_line_dot(self):549        # Test drawing a wide "line" from one point to another just draws550        # a single point551        # Arrange552        im = Image.new("RGB", (W, H))553        draw = ImageDraw.Draw(im)554        expected = "Tests/images/imagedraw_wide_line_dot.png"555        # Act556        draw.line([(50, 50), (50, 50)], width=3)557        # Assert558        self.assert_image_similar(im, Image.open(expected), 1)...EventBody2EventBodyMover.ts
Source:EventBody2EventBodyMover.ts  
1import EventBody from '../../Event/EventBody';2import { isOverlap, walkLoop } from '../../common/functions';3import { SN } from '../../common/definitions';4import { ExtensionManager } from '..';5import { Conflict as ComponentConflict } from '.';6import { Breakpoint } from '../BreakpointAnimation';7import { ConflictFixResult } from '../../types';8type Conflict = ComponentConflict<EventBody>;9export default class EventBody2EventBodyMover {10    constructor(public ext :ExtensionManager) {}11    conflicts :Conflict[] = [];12    /**13     * above EventBody is above, below EventBody is below14     * */15    eventBodyList :EventBody[] = [];16    spaceMap = new Map() as Map<EventBody, { top :number, bottom :number }>;17    static async avoid(18        { mover, fixed, direction }19        :{ mover :EventBody, fixed :EventBody, direction :1 | -1 },20    ) {21        if (direction > 0) {22            mover.drawInfo.offset.y += (fixed.drawInfo.box.y + fixed.drawInfo.box.height)23                - mover.drawInfo.box.y24                + 1;25        } else {26            mover.drawInfo.offset.y -= (mover.drawInfo.box.y + mover.drawInfo.box.height)27                - fixed.drawInfo.box.y28                + 1;29        }30        await mover.apply();31    }32    static isConflict(eb1 :EventBody, eb2 :EventBody) {33        if (eb1 === eb2) return false;34        if (eb1.drawInfo.floated !== eb2.drawInfo.floated) {35            const floated = (eb1.drawInfo.floated ? eb1 : eb2) as EventBody;36            const another = (eb1 === floated ? eb2 : eb1) as EventBody;37            if ( // floated's line overlapped with another's body38                (floated.drawInfo.markDrawInfo.target.y > another.drawInfo.box.y)39                && (40                    floated.drawInfo.markDrawInfo.target.y41                    < (another.drawInfo.box.y + another.drawInfo.box.height)42                )43            ) return true;44        }45        return isOverlap(eb1.drawInfo.box, eb2.drawInfo.box);46    }47    public async fix() :Promise<ConflictFixResult> {48        this.eventBodyList = Array.from(this.ext.components[SN.EventBody])49            .sort((eb1, eb2) => (50                eb1.drawInfo.markDrawInfo.target.y51                - eb2.drawInfo.markDrawInfo.target.y52            ));53        return await walkLoop(async () => [54            await this.tryFixOne(),55        ]).catch(() => ConflictFixResult.Failed);56    }57    /**58     * @return {boolean} have fixed one of conflicts?59     * */60    protected async tryFixOne() :Promise<ConflictFixResult> {61        await this.countConflict();62        this.countSpace();63        if (this.conflicts.length === 0) return ConflictFixResult.NoConflict;64        this.conflicts = this.conflicts.filter(65            conflict => this.isPossible(conflict),66        );67        if (this.conflicts.length === 0) return ConflictFixResult.Failed;68        const conflict = this.conflicts.find(69            conflict1 => this.conflicts.every(70                conflict2 => this.countCast(conflict1) <= this.countCast(conflict2),71            ),72        )!;73        const eventBodies = [74            conflict.self,75            ...conflict.with,76        ].sort(77            (eb1, eb2) => eb2.drawInfo.markDrawInfo.target.y - eb1.drawInfo.markDrawInfo.target.y,78        );79        const options = {80            components: [81                ...this.ext.components[SN.AxisBody],82                ...eventBodies.filter(eb => !eb.drawInfo.floated),83                ...eventBodies.filter(eb => eb.drawInfo.floated),84            ],85            protagonist: conflict.self,86        };87        await this.ext.breakpoint.block(Breakpoint.FixEventBody2EventBodyMover, options);88        await this.fixConflict(conflict);89        await this.ext.breakpoint.block(90            Breakpoint.FixEventBody2EventBodyMover,91            {92                ...options,93                forward: true,94            },95        );96        return ConflictFixResult.Alleviated;97    }98    protected isPossible(conflict :Conflict) {99        if (100            conflict.self.drawInfo.floated101            && conflict.with.some(eb => !eb.drawInfo.floated)102        ) return false;103        const needed = this.countNeeded(conflict);104        const space = this.spaceMap.get(conflict.self)!;105        return (needed.bottom === 0 || needed.top === 0)106            && (space.bottom >= needed.bottom && space.top >= needed.top);107    }108    protected async fixConflict(conflict :Conflict) {109        const needed = this.countNeeded(conflict);110        const moveDistance = needed.top ? needed.top : -needed.bottom;111        const direction = moveDistance / Math.abs(moveDistance) as (1 | -1);112        // fix conflict113        conflict.self.drawInfo.offset.y += moveDistance;114        await conflict.self.apply();115        // and fix side-effect116        const effectable = this.eventBodyList.filter(117            eb => eb.drawInfo.floated === conflict.self.drawInfo.floated,118        );119        for (120            let i = effectable.indexOf(conflict.self) + direction;121            i >= 0 && i < effectable.length;122            i += direction123        ) {124            const last = effectable[i - direction];125            const now = effectable[i];126            if (EventBody2EventBodyMover.isConflict(last, now)) {127                await EventBody2EventBodyMover.avoid({128                    direction,129                    mover: now,130                    fixed: last,131                });132            } else break;133        }134    }135    protected async countConflict() {136        this.conflicts.length = 0;137        await Promise.all(this.eventBodyList.map(eb => eb.apply()));138        for (const eb of this.eventBodyList) {139            const conflict = {140                self: eb,141                with: this.eventBodyList.filter(142                    target => EventBody2EventBodyMover.isConflict(eb, <EventBody>target),143                ) as EventBody[],144            };145            if (conflict.with.length) this.conflicts.push(conflict);146        }147    }148    protected countCast(conflict :Conflict) {149        const needed = this.countNeeded(conflict);150        return needed.bottom + needed.top;151    }152    /**153     * Count the number how many space needed for fix the conflict by verticalMove154     * */155    protected countNeeded(conflict :Conflict) :{ top :number, bottom :number } {156        const origin = conflict.self;157        const result = {158            top: 0,159            bottom: 0,160        };161        const above :EventBody[] = conflict.with.filter(162            cb => cb.drawInfo.markDrawInfo.target.y < origin.drawInfo.markDrawInfo.target.y,163        );164        const below :EventBody[] = conflict.with.filter(165            cb => cb.drawInfo.markDrawInfo.target.y > origin.drawInfo.markDrawInfo.target.y,166        );167        if (above.length) {168            result.top = Math.max(169                ...above.map((upper) => {170                    if (upper.drawInfo.floated === origin.drawInfo.floated) {171                        return (172                            upper.drawInfo.box.y173                            + upper.drawInfo.box.height174                            - origin.drawInfo.box.y175                        );176                    } else if (origin.drawInfo.floated) {177                        return ((178                            upper.drawInfo.box.y + upper.drawInfo.box.height)179                            - origin.drawInfo.markDrawInfo.target.y180                        );181                    } else if (upper.drawInfo.floated) {182                        return upper.drawInfo.markDrawInfo.target.y - origin.drawInfo.box.y;183                    }184                    throw SyntaxError('floated is not a boolean');185                }),186            );187        }188        if (below.length) {189            result.bottom = Math.max(190                ...below.map((lower) => {191                    const avoidBox = (192                        origin.drawInfo.box.y193                        + origin.drawInfo.box.height194                        - lower.drawInfo.box.y195                    );196                    if (lower.drawInfo.floated === origin.drawInfo.floated) {197                        return avoidBox;198                    } else if (origin.drawInfo.floated) {199                        const avoidFloatLine = origin.drawInfo.markDrawInfo.target.y200                            - lower.drawInfo.box.y;201                        return Math.max(202                            avoidBox,203                            avoidFloatLine,204                        );205                    } else if (lower.drawInfo.floated) {206                        const avoidFloatLine = (origin.drawInfo.box.y + origin.drawInfo.box.height)207                            - lower.drawInfo.markDrawInfo.target.y;208                        return Math.max(209                            avoidBox,210                            avoidFloatLine,211                        );212                    }213                    throw SyntaxError('floated is not a boolean');214                }),215            );216        }217        // margin 1 to target of conflict218        if (result.top) result.top++;219        if (result.bottom) result.bottom++;220        origin.extraData.needed = result;221        return result;222    }223    /**224     * Count the number how many space the component can move225     * */226    protected countSpace() {227        const spacePadding = 4; // FIXME: remove supported228        // Itself's can move space229        this.eventBodyList.forEach(230            eb => this.spaceMap.set(eb, {231                top: eb.drawInfo.markDrawInfo.target.y - eb.drawInfo.box.y - spacePadding,232                bottom: eb.drawInfo.box.y233                    + eb.drawInfo.box.height234                    - eb.drawInfo.markDrawInfo.target.y235                    - spacePadding236                ,237            }),238        );239        const applyLimiting = (allEventBody :EventBody[]) => {240            if (allEventBody.length === 0) return;241            // An item is limited from242            // it's first that prevent out of canvas243            const first = allEventBody[0];244            this.spaceMap.get(first)!.bottom = Math.min(245                this.spaceMap.get(first)!.bottom,246                first.drawInfo.box.y,247            );248            // it's last that prevent out of canvas249            const last = allEventBody[allEventBody.length - 1];250            this.spaceMap.get(last)!.top = Math.min(251                this.spaceMap.get(last)!.top,252                last.canvas.height - (last.drawInfo.box.y + last.drawInfo.box.height),253            );254            // clamp by neighbor255            for (let i = 1; i < allEventBody.length; i++) {256                const previous = allEventBody[i - 1];257                const now = allEventBody[i];258                const nowData = this.spaceMap.get(now)!;259                const previousData = this.spaceMap.get(previous)!;260                const distance = now.drawInfo.box.y261                    - (previous.drawInfo.box.y + previous.drawInfo.box.height);262                nowData.bottom = Math.min(263                    nowData.bottom,264                    distance + previousData.bottom,265                );266            }267            for (let i = allEventBody.length - 2; i >= 0; i--) {268                const next = allEventBody[i + 1];269                const now = allEventBody[i];270                const nowData = this.spaceMap.get(now)!;271                const nextData = this.spaceMap.get(next)!;272                const distance = next.drawInfo.box.y273                    - (now.drawInfo.box.y + now.drawInfo.box.height);274                nowData.top = Math.min(275                    nowData.top,276                    distance + nextData.top,277                );278            }279            // Set number which < 0 as 0280            Array.from(this.spaceMap.values()).forEach((value) => {281                value.top = Math.max(0, value.top);282                value.bottom = Math.max(0, value.bottom);283            });284        };285        applyLimiting(this.eventBodyList.filter(eb => eb.drawInfo.floated));286        applyLimiting(this.eventBodyList.filter(eb => !eb.drawInfo.floated));287        this.eventBodyList.forEach(eb => {288            eb.extraData.space = this.spaceMap.get(eb);289        });290    }...DrawSupport-test.jsx
Source:DrawSupport-test.jsx  
1/**2 * Copyright 2015, GeoSolutions Sas.3 * All rights reserved.4 *5 * This source code is licensed under the BSD-style license found in the6 * LICENSE file in the root directory of this source tree.7 */8import expect from 'expect';9import React from 'react';10import ReactDOM from 'react-dom';11import L from 'leaflet';12import DrawSupport from '../DrawSupport';13import {} from '../../../../test-resources/drawsupport/features';14describe('Leaflet DrawSupport', () => {15    var msNode;16    beforeEach((done) => {17        document.body.innerHTML = '<div id="map" style="heigth: 100px; width: 100px"></div><div id="ms"></div>';18        msNode = document.getElementById('ms');19        setTimeout(done);20    });21    afterEach((done) => {22        ReactDOM.unmountComponentAtNode(msNode);23        document.body.innerHTML = '';24        msNode = undefined;25        setTimeout(done);26    });27    it('test creation', () => {28        let map = L.map("map", {29            center: [51.505, -0.09],30            zoom: 1331        });32        const cmp = ReactDOM.render(33            <DrawSupport34                map={map}35                drawOwner="me"36            />37            , msNode);38        expect(cmp).toExist();39    });40    it('test circle drawing creation.', () => {41        let map = L.map("map", {42            center: [51.505, -0.09],43            zoom: 1344        });45        let cmp = ReactDOM.render(46            <DrawSupport47                map={map}48                drawOwner="me"49                options={{stopAfterDrawing: true}}50            />51            , msNode);52        expect(cmp).toExist();53        cmp = ReactDOM.render(54            <DrawSupport55                map={map}56                drawStatus="start"57                drawMethod="Circle"58                drawOwner="me"59                options={{stopAfterDrawing: true}}60            />61            , msNode);62        expect(map._layers).toExist();63    });64    it('test if drawing layers will be removed', () => {65        let map = L.map("map", {66            center: [51.505, -0.09],67            zoom: 1368        });69        let cmp = ReactDOM.render(70            <DrawSupport71                map={map}72                drawOwner="me"73                drawStatus="create"74                drawMethod="Point"75            />76            , msNode);77        cmp = ReactDOM.render(78            <DrawSupport79                map={map}80                drawOwner="me"81                drawStatus="create"82                drawMethod="BBOX"83            />84            , msNode);85        expect(cmp).toExist();86        cmp = ReactDOM.render(87            <DrawSupport88                map={map}89                drawOwner="me"90                drawStatus="clean"91                drawMethod="BBOX"92            />93            , msNode);94        expect(Object.keys(map._layers).length).toBe(0);95    });96    it('test draw replace', () => {97        let map = L.map("map", {98            center: [51.505, -0.09],99            zoom: 13100        });101        let cmp = ReactDOM.render(102            <DrawSupport103                map={map}104                drawOwner="me"105                drawStatus="create"106                drawMethod="LineString"107                options={{editEnabled: true}}108            />109            , msNode);110        cmp = ReactDOM.render(111            <DrawSupport112                map={map}113                drawOwner="me"114                drawStatus="create"115                drawMethod="LineString"116                options={{editEnabled: false}}117            />118            , msNode);119        expect(cmp).toExist();120        cmp = ReactDOM.render(121            <DrawSupport122                map={map}123                drawOwner="me"124                drawStatus="replace"125                drawMethod="LineString"126                features={[{127                    projection: "EPSG:4326",128                    coordinates: [[ -21150.703250721977, 5855989.620460]],129                    type: "LineString"}130                ]}131                options={{featureProjection: "EPSG:4326"}}132            />133            , msNode);134    });135    it('test editEnabled=true', () => {136        let map = L.map("map", {137            center: [51.505, -0.09],138            zoom: 13139        });140        let cmp = ReactDOM.render( <DrawSupport map={map} drawOwner="me" drawStatus="drawOrEdit" drawMethod="Point" features={[]} options={{editEnabled: false}} />, msNode);141        cmp = ReactDOM.render( <DrawSupport map={map} drawOwner="me" drawStatus="drawOrEdit" drawMethod="Point" features={[]} options={{editEnabled: true}} />, msNode);142        cmp = ReactDOM.render( <DrawSupport map={map} drawOwner="me" drawStatus="drawOrEdit" drawMethod="LineString" features={[]} options={{editEnabled: true}} />, msNode);143        cmp = ReactDOM.render( <DrawSupport map={map} drawOwner="me" drawStatus="drawOrEdit" drawMethod="Polygon" features={[]} options={{editEnabled: true}} />, msNode);144        cmp = ReactDOM.render( <DrawSupport map={map} drawOwner="me" drawStatus="drawOrEdit" drawMethod="MultiPoint" features={[]} options={{editEnabled: true}} />, msNode);145        cmp = ReactDOM.render( <DrawSupport map={map} drawOwner="me" drawStatus="drawOrEdit" drawMethod="MultiLineString" features={[]} options={{editEnabled: true}} />, msNode);146        cmp = ReactDOM.render( <DrawSupport map={map} drawOwner="me" drawStatus="drawOrEdit" drawMethod="MultiPolygon" features={[]} options={{editEnabled: true}} />, msNode);147        cmp = ReactDOM.render( <DrawSupport map={map} drawOwner="me" drawStatus="drawOrEdit" drawMethod="MultiPolygon" features={[]} options={{editEnabled: true}} />, msNode);148        expect(cmp).toExist();149    });150    it('test drawEnabled=true', () => {151        let map = L.map("map", {152            center: [51.505, -0.09],153            zoom: 13154        });155        let cmp = ReactDOM.render( <DrawSupport map={map} drawOwner="me" drawStatus="drawOrEdit" drawMethod="Point" features={[]} options={{drawEnabled: false}} />, msNode);156        cmp = ReactDOM.render( <DrawSupport map={map} drawOwner="me" drawStatus="drawOrEdit" drawMethod="Point" features={[]} options={{drawEnabled: true}} />, msNode);157        cmp = ReactDOM.render( <DrawSupport map={map} drawOwner="me" drawStatus="drawOrEdit" drawMethod="LineString" features={[]} options={{drawEnabled: true}} />, msNode);158        cmp = ReactDOM.render( <DrawSupport map={map} drawOwner="me" drawStatus="drawOrEdit" drawMethod="Polygon" features={[]} options={{drawEnabled: true}} />, msNode);159        cmp = ReactDOM.render( <DrawSupport map={map} drawOwner="me" drawStatus="drawOrEdit" drawMethod="MultiPoint" features={[]} options={{drawEnabled: true}} />, msNode);160        cmp = ReactDOM.render( <DrawSupport map={map} drawOwner="me" drawStatus="drawOrEdit" drawMethod="MultiLineString" features={[]} options={{drawEnabled: true}} />, msNode);161        cmp = ReactDOM.render( <DrawSupport map={map} drawOwner="me" drawStatus="drawOrEdit" drawMethod="MultiPolygon" features={[]} options={{drawEnabled: true}} />, msNode);162        expect(cmp).toExist();163    });164    it('test stop status', () => {165        let map = L.map("map", {166            center: [51.505, -0.09],167            zoom: 13168        });169        let cmp = ReactDOM.render( <DrawSupport map={map} drawOwner="me" drawStatus="start" drawMethod="LineString" options={{}} />, msNode);170        cmp = ReactDOM.render( <DrawSupport map={map} drawOwner="me" drawStatus="stop" drawMethod="LineString" options={{}} />, msNode);171        expect(cmp).toExist();172    });173    it('test updateSpatialField = true', () => {174        const latlngs = [[37, -109.05], [41, -109.03], [41, -102.05], [37, -102.04]];175        let map = L.map("map", {176            center: [51.505, -0.09],177            zoom: 13178        });179        let cmp = ReactDOM.render( <DrawSupport map={map} drawOwner="me" drawStatus="drawOrEdit" drawMethod="Polygon" features={[{180            type: "Feature",181            geometry: {182                type: "Polygon",183                coordinates: [latlngs]184            }185        }]} options={{drawEnabled: false, updateSpatialField: false}} />, msNode);186        cmp = ReactDOM.render( <DrawSupport map={map} drawOwner="me" drawStatus="drawOrEdit" drawMethod="Polygon" features={[{187            type: "Feature",188            geometry: {189                type: "Polygon",190                coordinates: [latlngs]191            }192        }]} options={{drawEnabled: false, updateSpatialField: true}} />, msNode);193        expect(cmp).toExist();194    });195    it('test endDrawing action', () => {196        const map = L.map("map", {197            center: [51.505, -0.09],198            zoom: 13199        });200        const actions = {201            onEndDrawing: () => {}202        };203        const spyonEndDrawing = expect.spyOn(actions, "onEndDrawing");204        ReactDOM.render(<DrawSupport205            drawMethod="Circle"206            drawOwner="me"207            map={map}208            features={[]}209            onEndDrawing={actions.onEndDrawing}/>, msNode);210        ReactDOM.render(<DrawSupport211            drawMethod="Circle"212            drawOwner="me"213            map={map}214            features={[{215                center: {x: -11271098, y: 7748880},216                coordinates: [-11271098, 7748880],217                projection: 'EPSG:3857',218                radius: 2000000,219                type: 'Polygon'220            }]}221            drawStatus="endDrawing"222            onEndDrawing={actions.onEndDrawing}/>, msNode);223        expect(spyonEndDrawing).toHaveBeenCalled();224    });225    it('test endDrawing action without features', () => {226        const map = L.map("map", {227            center: [51.505, -0.09],228            zoom: 13229        });230        const actions = {231            onEndDrawing: () => {}232        };233        const spyonEndDrawing = expect.spyOn(actions, "onEndDrawing");234        ReactDOM.render(<DrawSupport235            drawMethod="Circle"236            map={map}237            features={[]}238            onEndDrawing={actions.onEndDrawing}239            options={{geodesic: true}}/>, msNode);240        ReactDOM.render(<DrawSupport241            drawMethod="Circle"242            map={map}243            features={[]}244            drawStatus="endDrawing"245            onEndDrawing={actions.onEndDrawing}246            options={{geodesic: true}}/>, msNode);247        expect(spyonEndDrawing).toNotHaveBeenCalled();248    });...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
