From d1bb24a577bc01c66c220306ee4c9bc882c5cbc1 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Mon, 12 Sep 2022 09:31:19 -0700 Subject: [PATCH] Feature/collaborations updated (#1006) * Add availability help flyout (#734) Signed-off-by: Eugene Lee * Make common delete modal for components (#766) Signed-off-by: Eugene Lee * Sync app and app list types (#763) Signed-off-by: Eugene Lee * [WIP]: Cypress automation for Trace analytics dashboard application (#775) * Added cypress test cases for tooltip and search engine on Trace dashboard Signed-off-by: Pratibha Pandey * Added test cases for filters Signed-off-by: Pratibha Pandey * Added cypress test cases for tooltip and search engine on Trace dashboard Signed-off-by: Pratibha Pandey * Added test cases for filters Signed-off-by: Pratibha Pandey * Added test cases for Service page in Trace analytics Signed-off-by: Pratibha Pandey * Added Cypress test cases for trace analytics services spans table Signed-off-by: Deepak Nevde * Cypress test case for Traces Signed-off-by: Nidhi Singhai * Cypress test case for Traces Updated Signed-off-by: Nidhi Singhai * Worked on review comments Signed-off-by: Pratibha Pandey Co-authored-by: Deepak Nevde Co-authored-by: Nidhi Singhai * Feature/error toast on invalid valueoption selection 666 (#736) * rendered default axes selected and added error toasts on Save and Apply click if invalid value option selected Signed-off-by: rinku-kumar-psl * Cypress changes for error toasts on invalid value options selected Signed-off-by: rinku-kumar-psl * added constant VIZ_CONTAIN_XY_AXIS for x, y value axis Signed-off-by: rinku-kumar-psl * [Feature]: Treemap chart support in Event Analytics (#693) * Initial commit for treemap visualization Signed-off-by: Mrunal Zambre * changes to labelField, layout and config Signed-off-by: Mrunal Zambre * reverted changes of layoutConfig Signed-off-by: Mrunal Zambre * Cypress TestCase for TreeMap Signed-off-by: Nidhi Singhai * added new line Signed-off-by: Mrunal Zambre * updated test cases Signed-off-by: Mrunal Zambre * reverted snapshots Signed-off-by: Mrunal Zambre * implemented treemap config options Signed-off-by: Mrunal Zambre * added multicolored theme option Signed-off-by: Mrunal Zambre * updated snapshots Signed-off-by: Mrunal Zambre * Updated test scripts for multicolored section Signed-off-by: Pratibha Pandey * Fixed default selection for treemap Signed-off-by: Mrunal Zambre Co-authored-by: Nidhi Singhai Co-authored-by: Pratibha Pandey * Uses custom plugin to publish zips to maven (#786) Signed-off-by: Joshua Li * Cypress automation for Notebooks application (#809) * Added test cases for Notebooks application Signed-off-by: Pratibha Pandey * Added test cases for empty state of Notebooks table Signed-off-by: Pratibha Pandey * Feature/Pie chart legend, chart style, color theme and cypress test cases for same. (#776) * pie chart legends, chart color contrast and cypress test cases Signed-off-by: Deepak Nevde * Added color code in constants Signed-off-by: Deepak Nevde * Snapshots updated Signed-off-by: Deepak Nevde * Conflicts resolved Signed-off-by: Deepak Nevde * Review comment addressed Signed-off-by: Deepak Nevde * color variable changes Signed-off-by: Deepak Nevde * [Feature]: Heatmap- Color theme implementation in config panel (#778) * Implementation of color theme for heatmap Signed-off-by: ruchika-narang * refactoring code Signed-off-by: ruchika-narang * HeatMap Cypress TestCase Signed-off-by: Nidhi Singhai * Cypress TestCase for HeatMap Signed-off-by: Nidhi Singhai * Update Done according to Comment Signed-off-by: Nidhi Singhai * Refactored code Signed-off-by: ruchika-narang * Updated snapshot test case Signed-off-by: ruchika-narang * Fixed toast implementation and no result found for heatmap Signed-off-by: ruchika-narang * Undefined checks for value options Signed-off-by: ruchika-narang Co-authored-by: Nidhi Singhai * [Enhancement]: Pie Config Panel features v1 (#816) * updated dimensions and metrics UI for pie chart Signed-off-by: Mrunal Zambre * updated imports Signed-off-by: Mrunal Zambre * updated snapshots Signed-off-by: Mrunal Zambre * [Enhancement]: TreeMap Config Panel features v1 (#814) * added support for multiple parents in treemap Signed-off-by: Mrunal Zambre * minor type and position fixes Signed-off-by: Mrunal Zambre * added default values for color pickers Signed-off-by: Mrunal Zambre * resolved review comments Signed-off-by: Mrunal Zambre * TreeMap Enhancement TestCases Signed-off-by: Nidhi Singhai * TreeMap Enhancement TestCases Signed-off-by: Nidhi Singhai * TreeMap Enhancement TestCases Updated Signed-off-by: Nidhi Singhai * Update Done Signed-off-by: Nidhi Singhai * fixed default parent color pickers state Signed-off-by: Mrunal Zambre * fixed undefined check Signed-off-by: Mrunal Zambre * updated snapshots Signed-off-by: Mrunal Zambre Co-authored-by: Nidhi Singhai Co-authored-by: Subrat Pattnaik * Bar chart: Legend, Chart styles, and Color Theme features implementation on config panel - 697 (#780) * mode, orientation and rotate labels implementation under Chart style for Bar chart Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_button_group.tsx * LineWidth and Fill-opacity changes Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/utils/utils.tsx * Bar Group Width, Bar Width changes and rotated label hiding issue resolved Signed-off-by: rinku-kumar-psl * corner cases handled for bar with and group Width and conditionally rendered rotate label UI Signed-off-by: rinku-kumar-psl * Bar chart legend and color theme changes Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_legend.tsx * Snapshots updated Signed-off-by: rinku-kumar-psl * empty line added Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_button_group.tsx # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_legend.tsx * review comment addressed Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_legend.tsx * snapshot updated Signed-off-by: rinku-kumar-psl * PR review comment addressed. Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_button_group.tsx * add button constant added Signed-off-by: rinku-kumar-psl * changed rgba to rgb in bar.tsx Signed-off-by: rinku-kumar-psl * snapshot updated Signed-off-by: rinku-kumar-psl * bump version to 2.1.0 and bump gradle to 7.4.2 (#817) Signed-off-by: Kavitha Conjeevaram Mohan * 2.1 release notes (#839) Signed-off-by: Kavitha Conjeevaram Mohan * change 2.1 version bump PR under maintenance (#841) * change version bump to maintenance Signed-off-by: Kavitha Conjeevaram Mohan * change version bump to maintenance Signed-off-by: Kavitha Conjeevaram Mohan * Sprint1 : combine PR for visualization from Sprint1 (#824) * graph style section UI schema Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/visualizations/charts/lines/line_type.ts * changes for style mode and interpolation Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/visualizations/charts/lines/line_type.ts # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts * lineWidth integration for line mode Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/visualizations/charts/lines/line.tsx # dashboards-observability/public/components/visualizations/charts/lines/line_type.ts # Conflicts: # dashboards-observability/common/constants/shared.ts # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_style_slider.tsx * changes for Legend and Orientation in Line Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_button_group.tsx # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_legend.tsx # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_style_slider.tsx * point size and Bar Alignment changes Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/visualizations/charts/lines/line.tsx # dashboards-observability/public/components/visualizations/charts/lines/line_type.ts # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts # Conflicts: # dashboards-observability/common/constants/shared.ts # dashboards-observability/common/types/explorer.ts * implemented fill opacity for line chart Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/visualizations/charts/lines/line.tsx # Conflicts: # dashboards-observability/public/components/event_analytics/utils/utils.tsx * changes for line width and fill opacity in bar mode and removed mode from chartOption Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/common/constants/shared.ts * updated bar mode opacity in line chart Signed-off-by: rinku-kumar-psl * refactored the config chart style code Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts # Conflicts: # dashboards-observability/common/constants/shared.ts # dashboards-observability/common/types/explorer.ts * snapshot updated and code refactored Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/utils/utils.tsx * type added to new component Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_button_group.tsx # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_style_slider.tsx * review comments addressed Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/utils/utils.tsx # Conflicts: # dashboards-observability/common/constants/shared.ts * cypress test case added and resolve button label wraping issue Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/.cypress/integration/1_event_analytics.spec.js # dashboards-observability/.cypress/utils/event_constants.js # Conflicts: # dashboards-observability/.cypress/integration/1_event_analytics.spec.js # Conflicts: # dashboards-observability/.cypress/integration/1_event_analytics.spec.js * multi matrices changes for Line Signed-off-by: rinku-kumar-psl * dimensions and metrics UI changes for time-series Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/common/constants/explorer.ts # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/data_config_panel_item.tsx # dashboards-observability/public/components/event_analytics/explorer/visualizations/index.tsx * made data config pannel collapsable and initial fields render Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/data_config_panel_item.tsx # dashboards-observability/public/components/event_analytics/explorer/visualizations/index.tsx * code refactored Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/data_config_panel_item.tsx * snapshot updated and handled corner cases Signed-off-by: rinku-kumar-psl * code styling fixes and added TODO comment Signed-off-by: rinku-kumar-psl * table view: eui table replaced with ag-grid Signed-off-by: Ramneet Chopra * drag-drop issue fixed Signed-off-by: Ramneet Chopra * test case of data_table updated Signed-off-by: Ramneet Chopra * feedback comments resolved Signed-off-by: Ramneet Chopra * grid height issue:fixed Signed-off-by: Ramneet Chopra * column height, value getter for type double Signed-off-by: Ramneet Chopra * data_table elements moved to separate Signed-off-by: Ramneet Chopra * footer components Signed-off-by: Ramneet Chopra * cypress test cases for table view Signed-off-by: Ramneet Chopra * data config reviewed code added Signed-off-by: Deepak Nevde * Text correction Signed-off-by: Deepak Nevde * Conflicts resolved Signed-off-by: Deepak Nevde * enhancement for heatmap with new UI Signed-off-by: Shankha Das * line chart test cases Signed-off-by: Shankha Das * console logs removed Signed-off-by: Shankha Das * updated value options ui for treemap Signed-off-by: Mrunal Zambre * removed console Signed-off-by: Mrunal Zambre * sprint1-visualization-fixes. Signed-off-by: abasatwar * initialize default params for DimensonComponent and formatted the codes Signed-off-by: rinku-kumar-psl * code review changes done Signed-off-by: rinku-kumar-psl * added empty line at end. Signed-off-by: abasatwar Co-authored-by: rinku-kumar-psl Co-authored-by: Ramneet Chopra Co-authored-by: Deepak Nevde Co-authored-by: Shankha Das Co-authored-by: Mrunal Zambre * Bump moment from 2.29.2 to 2.29.4 in /dashboards-observability (#845) Bumps [moment](https://github.com/moment/moment) from 2.29.2 to 2.29.4. - [Release notes](https://github.com/moment/moment/releases) - [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md) - [Commits](https://github.com/moment/moment/compare/2.29.2...2.29.4) --- updated-dependencies: - dependency-name: moment dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Sprint2 (#47) (#868) * graph style section UI schema Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/visualizations/charts/lines/line_type.ts * changes for style mode and interpolation Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/visualizations/charts/lines/line_type.ts # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts * lineWidth integration for line mode Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/visualizations/charts/lines/line.tsx # dashboards-observability/public/components/visualizations/charts/lines/line_type.ts # Conflicts: # dashboards-observability/common/constants/shared.ts # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_style_slider.tsx * changes for Legend and Orientation in Line Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_button_group.tsx # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_legend.tsx # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_style_slider.tsx * point size and Bar Alignment changes Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/visualizations/charts/lines/line.tsx # dashboards-observability/public/components/visualizations/charts/lines/line_type.ts # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts # Conflicts: # dashboards-observability/common/constants/shared.ts # dashboards-observability/common/types/explorer.ts * implemented fill opacity for line chart Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/visualizations/charts/lines/line.tsx # Conflicts: # dashboards-observability/public/components/event_analytics/utils/utils.tsx * changes for line width and fill opacity in bar mode and removed mode from chartOption Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/common/constants/shared.ts * updated bar mode opacity in line chart Signed-off-by: rinku-kumar-psl * refactored the config chart style code Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts # Conflicts: # dashboards-observability/common/constants/shared.ts # dashboards-observability/common/types/explorer.ts * snapshot updated and code refactored Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/utils/utils.tsx * type added to new component Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_button_group.tsx # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_style_slider.tsx * review comments addressed Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/utils/utils.tsx # Conflicts: # dashboards-observability/common/constants/shared.ts * cypress test case added and resolve button label wraping issue Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/.cypress/integration/1_event_analytics.spec.js # dashboards-observability/.cypress/utils/event_constants.js # Conflicts: # dashboards-observability/.cypress/integration/1_event_analytics.spec.js # Conflicts: # dashboards-observability/.cypress/integration/1_event_analytics.spec.js * multi matrices changes for Line Signed-off-by: rinku-kumar-psl * dimensions and metrics UI changes for time-series Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/common/constants/explorer.ts # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/data_config_panel_item.tsx # dashboards-observability/public/components/event_analytics/explorer/visualizations/index.tsx * made data config pannel collapsable and initial fields render Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/data_config_panel_item.tsx # dashboards-observability/public/components/event_analytics/explorer/visualizations/index.tsx * code refactored Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/data_config_panel_item.tsx * snapshot updated and handled corner cases Signed-off-by: rinku-kumar-psl * code styling fixes and added TODO comment Signed-off-by: rinku-kumar-psl * sequence change for dimensions and metrics Signed-off-by: Deepak Nevde * Sprint1 (#14) * graph style section UI schema Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/visualizations/charts/lines/line_type.ts * changes for style mode and interpolation Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/visualizations/charts/lines/line_type.ts # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts * lineWidth integration for line mode Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/visualizations/charts/lines/line.tsx # dashboards-observability/public/components/visualizations/charts/lines/line_type.ts # Conflicts: # dashboards-observability/common/constants/shared.ts # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_style_slider.tsx * changes for Legend and Orientation in Line Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_button_group.tsx # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_legend.tsx # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_style_slider.tsx * point size and Bar Alignment changes Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/visualizations/charts/lines/line.tsx # dashboards-observability/public/components/visualizations/charts/lines/line_type.ts # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts # Conflicts: # dashboards-observability/common/constants/shared.ts # dashboards-observability/common/types/explorer.ts * implemented fill opacity for line chart Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/visualizations/charts/lines/line.tsx # Conflicts: # dashboards-observability/public/components/event_analytics/utils/utils.tsx * changes for line width and fill opacity in bar mode and removed mode from chartOption Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/common/constants/shared.ts * updated bar mode opacity in line chart Signed-off-by: rinku-kumar-psl * refactored the config chart style code Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/index.ts # Conflicts: # dashboards-observability/common/constants/shared.ts # dashboards-observability/common/types/explorer.ts * snapshot updated and code refactored Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/utils/utils.tsx * type added to new component Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_button_group.tsx # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_style_slider.tsx * review comments addressed Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/utils/utils.tsx # Conflicts: # dashboards-observability/common/constants/shared.ts * cypress test case added and resolve button label wraping issue Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/.cypress/integration/1_event_analytics.spec.js # dashboards-observability/.cypress/utils/event_constants.js # Conflicts: # dashboards-observability/.cypress/integration/1_event_analytics.spec.js # Conflicts: # dashboards-observability/.cypress/integration/1_event_analytics.spec.js * multi matrices changes for Line Signed-off-by: rinku-kumar-psl * dimensions and metrics UI changes for time-series Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/common/constants/explorer.ts # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/data_config_panel_item.tsx # dashboards-observability/public/components/event_analytics/explorer/visualizations/index.tsx * made data config pannel collapsable and initial fields render Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/data_config_panel_item.tsx # dashboards-observability/public/components/event_analytics/explorer/visualizations/index.tsx * code refactored Signed-off-by: rinku-kumar-psl # Conflicts: # dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/data_config_panel_item.tsx * snapshot updated and handled corner cases Signed-off-by: rinku-kumar-psl * code styling fixes and added TODO comment Signed-off-by: rinku-kumar-psl * data config reviewed code added Signed-off-by: Deepak Nevde * Text correction Signed-off-by: Deepak Nevde * Conflicts resolved Signed-off-by: Deepak Nevde * table view: eui table replaced with ag-grid Signed-off-by: Ramneet Chopra * drag-drop issue fixed Signed-off-by: Ramneet Chopra * test case of data_table updated Signed-off-by: Ramneet Chopra * feedback comments resolved Signed-off-by: Ramneet Chopra * grid height issue:fixed Signed-off-by: Ramneet Chopra * column height, value getter for type double Signed-off-by: Ramneet Chopra * data_table elements moved to separate Signed-off-by: Ramneet Chopra * footer components Signed-off-by: Ramneet Chopra * cypress test cases for table view Signed-off-by: Ramneet Chopra * enhancement for heatmap with new UI Signed-off-by: Shankha Das * line chart test cases Signed-off-by: Shankha Das * console logs removed Signed-off-by: Shankha Das * updated value options ui for treemap Signed-off-by: Mrunal Zambre * removed console Signed-off-by: Mrunal Zambre * Fixes of sprint1 for new ui implementation (#12) Signed-off-by: ruchika-narang Co-authored-by: rinku-kumar-psl Co-authored-by: Deepak Nevde Co-authored-by: Ramneet Chopra Co-authored-by: Shankha Das Co-authored-by: Mrunal Zambre Co-authored-by: ruchika-narang <79983862+ruchika-narang@users.noreply.github.com> * Latest code added Signed-off-by: Deepak Nevde * Collapsapable button position change to top Signed-off-by: Deepak Nevde * table view: eui table replaced with ag-grid Signed-off-by: Ramneet Chopra * drag-drop issue fixed Signed-off-by: Ramneet Chopra * test case of data_table updated Signed-off-by: Ramneet Chopra * feedback comments resolved Signed-off-by: Ramneet Chopra * grid height issue:fixed Signed-off-by: Ramneet Chopra * column height, value getter for type double Signed-off-by: Ramneet Chopra * data_table elements moved to separate Signed-off-by: Ramneet Chopra * footer components Signed-off-by: Ramneet Chopra * cypress test cases for table view Signed-off-by: Ramneet Chopra * data config reviewed code added Signed-off-by: Deepak Nevde * Text correction Signed-off-by: Deepak Nevde * Conflicts resolved Signed-off-by: Deepak Nevde * enhancement for heatmap with new UI Signed-off-by: Shankha Das * line chart test cases Signed-off-by: Shankha Das * console logs removed Signed-off-by: Shankha Das * updated value options ui for treemap Signed-off-by: Mrunal Zambre * removed console Signed-off-by: Mrunal Zambre * sprint1-visualization-fixes. Signed-off-by: abasatwar * added colorscale config options for treemap Signed-off-by: Mrunal Zambre * code review comment resolved Signed-off-by: Deepak Nevde * added config option to sort treemap sectors Signed-off-by: Mrunal Zambre * changes to resctct duplicte options Signed-off-by: rinku-kumar-psl * Updated and Added test scripts for Treemap chart along with data config and worked on reassembling the event_constants.js file Signed-off-by: Pratibha Pandey * Removed unwanted code Signed-off-by: Pratibha Pandey * implementation of histogram with new UI Signed-off-by: ruchika-narang * gauge chart added Signed-off-by: Ramneet Chopra * Pie chart enhancement, multi labels change Signed-off-by: Deepak Nevde * threshold text fix Signed-off-by: Ramneet Chopra * cypress test cases added Signed-off-by: Ramneet Chopra * Code review comment resolved Signed-off-by: Deepak Nevde * reset fixed, unused imports removed, PR checks fixed Signed-off-by: Ramneet Chopra * single timestamp dimension, no data dsiplay, label rotate, label/legend size Signed-off-by: Ramneet Chopra * layout fixed for primary y axis Signed-off-by: Ramneet Chopra * change of screen size of no data found and visualization Signed-off-by: Shankha Das * changes for restriction of duplicate fields on Data Config and only numeric field selection to metrics Signed-off-by: rinku-kumar-psl * line label replaced with time series Signed-off-by: Ramneet Chopra * snapshot tests Signed-off-by: Ramneet Chopra * Removed unwanted spaces Signed-off-by: Pratibha Pandey * initialize default params for DimensonComponent and formatted the codes Signed-off-by: rinku-kumar-psl * pr review feedback Signed-off-by: Ramneet Chopra * updated preview functionality for charts Signed-off-by: Mrunal Zambre * updated snapshots Signed-off-by: Mrunal Zambre * Worked on review comments Signed-off-by: Pratibha Pandey * changed variable names Signed-off-by: Mrunal Zambre * code review changes done Signed-off-by: rinku-kumar-psl * added empty line at end. Signed-off-by: abasatwar * updated variable names Signed-off-by: Mrunal Zambre * updated snapshots Signed-off-by: Mrunal Zambre * Added pie chart test cases Signed-off-by: Pratibha Pandey * updated snapshots Signed-off-by: ruchika-narang * Removed consoles Signed-off-by: ruchika-narang * Worked on conflicts Signed-off-by: Pratibha Pandey * color selector added Signed-off-by: Ramneet Chopra * updated snapshots Signed-off-by: ruchika-narang * UI updated as recommended Signed-off-by: Shankha Das * Added legend to heatmap Signed-off-by: ruchika-narang * data_config_panel_item timeseries code removed Signed-off-by: Ramneet Chopra * bar chart with multiple dimension and metrics, timestamp Signed-off-by: abasatwar * limit no. of gauge option added Signed-off-by: Ramneet Chopra * threshold limit added, gauge default parameters moved to constants/explorer Signed-off-by: Ramneet Chopra * legend placement added Signed-off-by: Ramneet Chopra * yarn test Signed-off-by: Ramneet Chopra * snapshot updated Signed-off-by: abasatwar * snapshot updated Signed-off-by: abasatwar * Resolving issues after removal of preview functionality Signed-off-by: ruchika-narang * updated snapshots Signed-off-by: ruchika-narang * Updated snapshots Signed-off-by: ruchika-narang * changes for default timestamp data for time-series and corner cases Signed-off-by: rinku-kumar-psl * code review comment addressed Signed-off-by: rinku-kumar-psl * pr feedback Signed-off-by: Ramneet Chopra * dimensions, metrics length checks refined Signed-off-by: Ramneet Chopra * updated as per review comments Signed-off-by: abasatwar * fixing of data config corner cases Signed-off-by: rinku-kumar-psl * snapshot updated Signed-off-by: abasatwar * pr feedback Signed-off-by: Ramneet Chopra Co-authored-by: rinku-kumar-psl Co-authored-by: Deepak Nevde Co-authored-by: Ramneet Chopra Co-authored-by: Shankha Das Co-authored-by: Mrunal Zambre Co-authored-by: ruchika-narang <79983862+ruchika-narang@users.noreply.github.com> Co-authored-by: Pratibha Pandey Co-authored-by: ruchika-narang Co-authored-by: Shankha Das Co-authored-by: rinku-kumar-psl Co-authored-by: Deepak Nevde Co-authored-by: Ramneet Chopra Co-authored-by: Shankha Das Co-authored-by: Mrunal Zambre Co-authored-by: ruchika-narang <79983862+ruchika-narang@users.noreply.github.com> Co-authored-by: Pratibha Pandey Co-authored-by: ruchika-narang Co-authored-by: Shankha Das * Staging for version increment automation (#848) * Version increment automation Signed-off-by: pgodithi * Version increment automation Signed-off-by: pgodithi * Version increment automation: task rename updateVersion Signed-off-by: pgodithi * Release Notes for 2.2.0 (#920) Signed-off-by: vamsi-amazon * Sprint2 code refactoring and warning minimization (#904) * changes to remove for unique key warning on Dom and code refactoring sprint2 Signed-off-by: rinku-kumar-psl * snapshot updated Signed-off-by: rinku-kumar-psl * no_results.test.tsx snapshot updated Signed-off-by: rinku-kumar-psl * added empty line at the end of the file Signed-off-by: rinku-kumar-psl * Bump to 2.2.0 (#918) (#928) * Bump to 2.2.0 Signed-off-by: vamsi-amazon * Update snapshots Signed-off-by: Joshua Li Co-authored-by: Joshua Li (cherry picked from commit da9e9c013e13e03afd09d324e06e025dbb207f0c) Co-authored-by: vamsi-amazon * Sprint3 alpha (#64) (#931) * Sprint3 alpha (#64) Signed-off-by: abasatwar * issues resolved and snapshots updated Signed-off-by: Shankha Das * 2 snapshots updated Signed-off-by: Shankha Das Signed-off-by: abasatwar Signed-off-by: Shankha Das Co-authored-by: Shankha Das * [ENHANCEMENT]: Movement of temporary visualization panel data into userconfig (#929) * Worked on movement of data to userConfigs Signed-off-by: ruchika-narang * Updated snapshots Signed-off-by: ruchika-narang * Updated snapshots Signed-off-by: ruchika-narang * Updated snapshots for failing checks Signed-off-by: ruchika-narang * resolved PR comments Signed-off-by: Shankha Das * visType added Signed-off-by: Shankha Das Signed-off-by: ruchika-narang Signed-off-by: Shankha Das Co-authored-by: Shankha Das * cypress test case for horizontal bar (#935) Signed-off-by: nidhisinghai Signed-off-by: nidhisinghai Co-authored-by: nidhisinghai * build error resolve (#923) Signed-off-by: nidhisinghai Signed-off-by: nidhisinghai Co-authored-by: nidhisinghai * [BUG] : Dimensions getting removed when no timeseries field is present (#944) * Fix for app crash and dimension disaapearing Signed-off-by: ruchika-narang * optimized the code and updated snapshots Signed-off-by: Shankha Das * resolved PR comments Signed-off-by: Shankha Das Signed-off-by: ruchika-narang Signed-off-by: Shankha Das Co-authored-by: Shankha Das * cypress test case for scatter chart (#930) Signed-off-by: nidhisinghai Signed-off-by: nidhisinghai Co-authored-by: nidhisinghai * Bug/logs-view-data-config: Added Columns in Data Configuration for Logs View (#955) * Fix for app crash and dimension disaapearing Signed-off-by: ruchika-narang * optimized the code and updated snapshots Signed-off-by: Shankha Das * resolved PR comments Signed-off-by: Shankha Das * resolved data configuration bug for logs view Signed-off-by: Shankha Das Signed-off-by: ruchika-narang Signed-off-by: Shankha Das Co-authored-by: ruchika-narang * Feature/tooltip-section: Added tooltip options for various charts (#952) * Fix for app crash and dimension disaapearing Signed-off-by: ruchika-narang * optimized the code and updated snapshots Signed-off-by: Shankha Das * resolved PR comments Signed-off-by: Shankha Das * added tooltip options Signed-off-by: Shankha Das * removed log Signed-off-by: Shankha Das Signed-off-by: ruchika-narang Signed-off-by: Shankha Das Co-authored-by: ruchika-narang * resolved color theme issue (#960) Signed-off-by: Shankha Das Signed-off-by: Shankha Das * Renamed data panel to style (#964) Signed-off-by: ruchika-narang Signed-off-by: ruchika-narang * Query Manager (#915) * Bump prismjs from 1.25.0 to 1.27.0 in /dashboards-observability (#508) (#574) Bumps [prismjs](https://github.com/PrismJS/prism) from 1.25.0 to 1.27.0. - [Release notes](https://github.com/PrismJS/prism/releases) - [Changelog](https://github.com/PrismJS/prism/blob/master/CHANGELOG.md) - [Commits](https://github.com/PrismJS/prism/compare/v1.25.0...v1.27.0) --- updated-dependencies: - dependency-name: prismjs dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> (cherry picked from commit b4f491a16f81725db6d63f604a3020e5b89dd720) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * change to support java 8 in compile and runtime (#575) (#576) Signed-off-by: Zhongnan Su (cherry picked from commit 5c43e9dac336b37fa4f6f002709e0965015383aa) Co-authored-by: Zhongnan Su * Add 1.3.0 release notes (#580) (#582) Signed-off-by: Eugene Lee * query manager Signed-off-by: Eric Wei * removed aggregations from dimensions Signed-off-by: Eric Wei * qm improvements Signed-off-by: Eric Wei * types/code cleanups/error corrections Signed-off-by: Eric Wei * fixed a undefined issue Signed-off-by: Eric Wei * qm fixes for query builder Signed-off-by: Eric Wei * viz timestamp selector Signed-off-by: Eric Wei * use postinstall for antlr output files Signed-off-by: Eric Wei * query building fixes Signed-off-by: Eric Wei * updated snapshots Signed-off-by: Eric Wei * remove output files Signed-off-by: Eric Wei * cherry-pick from integration branch Signed-off-by: Eric Wei * explicitly remove generated files Signed-off-by: Eric Wei Signed-off-by: Eugene Lee Signed-off-by: Eric Wei Co-authored-by: opensearch-trigger-bot[bot] <98922864+opensearch-trigger-bot[bot]@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Zhongnan Su * Query manager integration (#987) * Bump prismjs from 1.25.0 to 1.27.0 in /dashboards-observability (#508) (#574) Bumps [prismjs](https://github.com/PrismJS/prism) from 1.25.0 to 1.27.0. - [Release notes](https://github.com/PrismJS/prism/releases) - [Changelog](https://github.com/PrismJS/prism/blob/master/CHANGELOG.md) - [Commits](https://github.com/PrismJS/prism/compare/v1.25.0...v1.27.0) --- updated-dependencies: - dependency-name: prismjs dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> (cherry picked from commit b4f491a16f81725db6d63f604a3020e5b89dd720) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * change to support java 8 in compile and runtime (#575) (#576) Signed-off-by: Zhongnan Su (cherry picked from commit 5c43e9dac336b37fa4f6f002709e0965015383aa) Co-authored-by: Zhongnan Su * Add 1.3.0 release notes (#580) (#582) Signed-off-by: Eugene Lee * query manager Signed-off-by: Eric Wei * removed aggregations from dimensions Signed-off-by: Eric Wei * qm improvements Signed-off-by: Eric Wei * types/code cleanups/error corrections Signed-off-by: Eric Wei * qm fixes for query builder Signed-off-by: Eric Wei * viz timestamp selector Signed-off-by: Eric Wei * query manager integration with bar step 1 Signed-off-by: Eric Wei * span fix Signed-off-by: Eric Wei * use postinstall for antlr output files Signed-off-by: Eric Wei * query building fix Signed-off-by: Eric Wei * updated snapshots Signed-off-by: Eric Wei * fixed file not found issue Signed-off-by: Eric Wei * remove output files Signed-off-by: Eric Wei Signed-off-by: Eugene Lee Signed-off-by: Eric Wei Co-authored-by: opensearch-trigger-bot[bot] <98922864+opensearch-trigger-bot[bot]@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Zhongnan Su * Bug/color-theme-options: Resolved color theme issue #960 (#971) * Resolved to show only metrics in the dropdown instead of all the fields Signed-off-by: ruchika-narang * Removed unncessary import Signed-off-by: ruchika-narang * Updated snapshots after rebasing with main Signed-off-by: ruchika-narang Signed-off-by: ruchika-narang * cypress box plot (#983) * cypress box plot Signed-off-by: nidhisinghai * cypress box plot new Signed-off-by: nidhisinghai Signed-off-by: nidhisinghai Co-authored-by: nidhisinghai * fix: reset fontSize on click of reset (#986) Signed-off-by: SivaprasadAluri Signed-off-by: SivaprasadAluri * Cypress automation for Logs view (#995) * Added cypress scripts for Logs view Signed-off-by: Pratibha Pandey * Added screenshots files Signed-off-by: Pratibha Pandey * Added snapshots files Signed-off-by: Pratibha Pandey Signed-off-by: Pratibha Pandey Signed-off-by: Eugene Lee Signed-off-by: rinku-kumar-psl Signed-off-by: Joshua Li Signed-off-by: Pratibha Pandey Signed-off-by: Deepak Nevde Signed-off-by: Mrunal Zambre Signed-off-by: Kavitha Conjeevaram Mohan Signed-off-by: pgodithi Signed-off-by: vamsi-amazon Signed-off-by: abasatwar Signed-off-by: Shankha Das Signed-off-by: ruchika-narang Signed-off-by: nidhisinghai Signed-off-by: Eric Wei Signed-off-by: SivaprasadAluri Co-authored-by: Eugene Lee Co-authored-by: Pratibha <103417380+pratibhapandey16@users.noreply.github.com> Co-authored-by: Deepak Nevde Co-authored-by: Nidhi Singhai Co-authored-by: Rinku Kumar <103560761+rinku-kumar-psl@users.noreply.github.com> Co-authored-by: Mrunal Zambre <79525611+mrunal-z@users.noreply.github.com> Co-authored-by: Pratibha Pandey Co-authored-by: Joshua Li Co-authored-by: deepaknevdepsl <102342039+deepaknevdepsl@users.noreply.github.com> Co-authored-by: ruchika-narang <79983862+ruchika-narang@users.noreply.github.com> Co-authored-by: Subrat Pattnaik Co-authored-by: Kavitha Conjeevaram Mohan Co-authored-by: abasatwar Co-authored-by: rinku-kumar-psl Co-authored-by: Ramneet Chopra Co-authored-by: Shankha Das Co-authored-by: Mrunal Zambre Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: ruchika-narang Co-authored-by: Shankha Das Co-authored-by: Prudhvi Godithi Co-authored-by: vamsi-amazon Co-authored-by: opensearch-trigger-bot[bot] <98922864+opensearch-trigger-bot[bot]@users.noreply.github.com> Co-authored-by: nidhisinghai <103416937+nidhisinghai@users.noreply.github.com> Co-authored-by: nidhisinghai Co-authored-by: shankha-das <93648901+shankha-das@users.noreply.github.com> Co-authored-by: Eric Wei Co-authored-by: Zhongnan Su Co-authored-by: SivaprasadAluri <110654651+SivaprasadAluri@users.noreply.github.com> Co-authored-by: Li --- ...-observability-test-and-build-workflow.yml | 2 +- .../integration/1_event_analytics.spec.js | 504 +- .../.cypress/integration/2_notebooks.spec.js | 34 + .../4_trace_analytics_dashboard.spec.js | 105 + .../5_trace_analytics_services.spec.js | 160 +- .../6_trace_analytics_traces.spec.js | 40 + .../integration/7_app_analytics.spec.js | 6 +- .../10_scatter_chart.spec.js | 228 + .../11_horizontalBar_chart.spec.js | 244 + .../12_boxPlot_chart.spec.js | 248 + .../VisualizationCharts/13_logsView.spec.js | 241 + .../9_coordinateMap_chart.spec.js | 195 + .../.cypress/utils/constants.js | 21 + .../.cypress/utils/event_constants.js | 199 +- dashboards-observability/.gitignore | 1 + .../common/constants/colors.ts | 186 + .../common/constants/data_table.ts | 16 + .../common/constants/explorer.ts | 77 +- .../common/constants/shared.ts | 86 +- .../adaptors/case_insensitive_char_stream.ts | 60 + .../grammar/.antlr/OpenSearchPPLLexer.interp | 831 + .../grammar/.antlr/OpenSearchPPLLexer.java | 1277 ++ .../grammar/.antlr/OpenSearchPPLLexer.tokens | 527 + .../antlr/grammar/OpenSearchPPLLexer.g4 | 333 + .../antlr/grammar/OpenSearchPPLParser.g4 | 475 + .../query_manager/antlr/ppl_syntax_parser.ts | 30 + .../ast/builder/query_builder.ts | 8 + .../ast/builder/stats_ast_builder.ts | 228 + .../ast/builder/stats_builder.ts | 135 + .../ast/expression/AggregateFunction.ts | 37 + .../ast/expression/AggregateTerm.ts | 31 + .../query_manager/ast/expression/field.ts | 20 + .../query_manager/ast/expression/group_by.ts | 31 + .../query_manager/ast/expression/index.ts | 6 + .../query_manager/ast/expression/span.ts | 28 + .../ast/expression/spanExpression.ts | 30 + .../common/query_manager/ast/index.ts | 6 + .../common/query_manager/ast/node.ts | 31 + .../query_manager/ast/tree/aggragations.ts | 58 + .../common/query_manager/ast/types/index.ts | 17 + .../common/query_manager/ast/types/stats.ts | 74 + .../common/query_manager/index.ts | 6 + .../common/query_manager/ppl_query_manager.ts | 17 + .../query_manager/query_builder/index.ts | 6 + .../query_builder/ppl_query_builder.ts | 39 + .../query_manager/query_parser/index.ts | 6 + .../query_parser/ppl_query_parser.ts | 25 + .../common/query_manager/utils/index.ts | 42 + ..._analytics.ts => application_analytics.ts} | 21 +- .../common/types/explorer.ts | 66 +- .../opensearch_dashboards.json | 4 +- dashboards-observability/package.json | 12 +- dashboards-observability/public/.DS_Store | Bin 0 -> 6148 bytes .../components/app_table.tsx | 31 +- .../components/application.tsx | 18 +- .../config_components/service_config.tsx | 2 +- .../config_components/trace_config.tsx | 2 +- .../components/configuration.tsx | 9 +- .../components/create.tsx | 15 +- .../availability_info_flyout.tsx | 62 + .../application_analytics/helpers/types.tsx | 10 - .../application_analytics/helpers/utils.tsx | 39 +- .../components/application_analytics/home.tsx | 27 +- .../common/helpers/delete_modal.tsx | 79 + .../components/common/search/autocomplete.tsx | 10 +- .../components/common/search/search.tsx | 17 +- .../custom_panels/custom_panel_table.tsx | 5 +- .../custom_panels/custom_panel_view.tsx | 5 +- .../modal_container.test.tsx.snap | 2 +- .../__snapshots__/utils.test.tsx.snap | 3718 ++- .../__tests__/modal_container.test.tsx | 7 +- .../helpers/modal_containers.tsx | 58 - .../custom_panels/helpers/utils.tsx | 1 + .../panel_modules/panel_grid/panel_grid.tsx | 3 +- .../visualization_flyout.test.tsx.snap | 4 +- .../event_analytics/explorer/explorer.tsx | 75 +- .../explorer/visualizations/app.scss | 29 + .../__snapshots__/config_panel.test.tsx.snap | 18732 ++++++++++++---- .../__tests__/config_panel.test.tsx | 3 +- .../config_panel/config_panel.scss | 15 +- .../config_panel/config_panel.tsx | 120 +- .../config_panel/config_panel_footer.tsx | 19 - .../config_controls/config_availability.tsx | 16 +- .../config_bar_chart_styles.tsx | 112 + .../config_controls/config_button_group.tsx | 40 + .../config_controls/config_chart_options.tsx | 137 +- .../config_color_palette_picker.tsx | 113 + .../config_controls/config_color_theme.tsx | 128 + .../config_controls/config_gauge_options.tsx | 8 +- .../config_heatmap_color_palette_picker.tsx | 43 + .../config_controls/config_legend.tsx | 65 + .../config_line_chart_styles.tsx | 125 + .../config_controls/config_logs_view.tsx | 110 + .../config_controls/config_number_input.tsx | 47 + .../config_controls/config_panel_item.tsx | 7 +- .../config_panel_option_gauge.tsx | 53 + .../config_controls/config_panel_options.tsx | 58 +- .../config_single_color_picker.tsx | 52 + .../config_controls/config_style_slider.tsx | 48 + .../config_controls/config_switch.tsx | 30 + .../config_controls/config_switch_button.tsx | 25 + .../config_controls/config_thresholds.tsx | 24 +- .../config_controls/config_tooltip.tsx | 58 + .../config_treemap_parents.tsx | 99 + .../config_controls/config_value_options.tsx | 46 +- .../data_config_panel_item.tsx | 558 + .../config_panes/config_controls/index.ts | 13 + .../logs_view_config_panel_item.tsx | 237 + .../treemap_config_panel_item.tsx | 180 + .../config_panes/default_vis_editor.tsx | 1 + .../explorer/visualizations/index.tsx | 97 +- .../shared_components.test.tsx.snap | 10 +- .../shared_components/empty_placeholder.scss | 12 + .../shared_components/empty_placeholder.tsx | 7 +- .../workspace_panel/workspace_panel.tsx | 16 +- .../components/event_analytics/home/home.tsx | 4 +- .../event_analytics/hooks/use_fetch_events.ts | 1 + .../hooks/use_fetch_visualizations.ts | 28 +- .../event_analytics/utils/utils.tsx | 73 +- .../span_detail_flyout.test.tsx.snap | 2 +- .../__tests__/__snapshots__/bar.test.tsx.snap | 476 +- .../__snapshots__/data_table.test.tsx.snap | 585 +- .../__snapshots__/heatmap.test.tsx.snap | 263 +- .../__snapshots__/histogram.test.tsx.snap | 672 + .../__snapshots__/line.test.tsx.snap | 456 +- .../__snapshots__/logs_view.test.tsx.snap | 586 + .../__tests__/__snapshots__/pie.test.tsx.snap | 466 +- .../__snapshots__/text.test.tsx.snap | 253 +- .../__snapshots__/treemap.test.tsx.snap | 697 + .../charts/__tests__/data_table.test.tsx | 17 +- .../charts/__tests__/histogram.test.tsx | 30 + .../charts/__tests__/logs_view.test.tsx | 30 + .../charts/__tests__/treemap.test.tsx | 30 + .../visualizations/charts/bar/bar.tsx | 204 +- .../visualizations/charts/bar/bar_type.ts | 183 +- .../charts/bar/horizontal_bar_type.ts | 14 +- .../charts/bubble/bubble_type.ts | 8 +- .../charts/data_table/data_table.scss | 63 + .../charts/data_table/data_table.tsx | 277 +- .../charts/data_table/data_table_footer.tsx | 126 + .../charts/data_table/data_table_header.tsx | 195 + .../charts/data_table/data_table_type.ts | 6 +- .../charts/financial/gauge/gauge.tsx | 172 +- .../charts/financial/gauge/gauge_type.ts | 95 +- .../charts/helpers/viz_types.ts | 140 +- .../charts/histogram/histogram.tsx | 106 +- .../charts/histogram/histogram_type.ts | 98 +- .../visualizations/charts/lines/line.tsx | 171 +- .../visualizations/charts/lines/line_type.ts | 203 +- .../charts/logs_view/logs_view.scss | 25 + .../charts/logs_view/logs_view.tsx | 40 + .../charts/logs_view/logs_view_type.ts | 69 + .../visualizations/charts/maps/heatmap.tsx | 83 +- .../charts/maps/heatmap_type.ts | 92 +- .../charts/maps/treemap_type.ts | 110 +- .../visualizations/charts/maps/treemaps.tsx | 238 +- .../visualizations/charts/pie/pie.tsx | 120 +- .../visualizations/charts/pie/pie_type.ts | 99 +- .../charts/shared/shared_configs.ts | 2 +- .../visualizations/charts/text/text_type.ts | 16 +- .../visualizations/charts/vis_types.ts | 3 + .../visualizations/visualization.tsx | 5 +- .../visualizations/visualization_chart.tsx | 10 +- .../public/services/requests/ppl.ts | 2 +- .../app_analytics_adaptor.ts | 73 +- .../app_analytics_router.ts | 14 +- .../test/event_analytics_constants.ts | 13 +- dashboards-observability/yarn.lock | 98 +- opensearch-observability/.gitignore | 2 + opensearch-observability/build.gradle | 44 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- opensearch-observability/scripts/build.sh | 82 + .../observability/PluginRestTestCase.kt | 2 +- ...rch-observability.release-notes-2.1.0.0.md | 15 + ...rch-observability.release-notes-2.2.0.0.md | 5 + 175 files changed, 32971 insertions(+), 7825 deletions(-) create mode 100644 dashboards-observability/.cypress/integration/VisualizationCharts/10_scatter_chart.spec.js create mode 100644 dashboards-observability/.cypress/integration/VisualizationCharts/11_horizontalBar_chart.spec.js create mode 100644 dashboards-observability/.cypress/integration/VisualizationCharts/12_boxPlot_chart.spec.js create mode 100644 dashboards-observability/.cypress/integration/VisualizationCharts/13_logsView.spec.js create mode 100644 dashboards-observability/.cypress/integration/VisualizationCharts/9_coordinateMap_chart.spec.js create mode 100644 dashboards-observability/common/constants/colors.ts create mode 100644 dashboards-observability/common/constants/data_table.ts create mode 100644 dashboards-observability/common/query_manager/antlr/adaptors/case_insensitive_char_stream.ts create mode 100644 dashboards-observability/common/query_manager/antlr/grammar/.antlr/OpenSearchPPLLexer.interp create mode 100644 dashboards-observability/common/query_manager/antlr/grammar/.antlr/OpenSearchPPLLexer.java create mode 100644 dashboards-observability/common/query_manager/antlr/grammar/.antlr/OpenSearchPPLLexer.tokens create mode 100644 dashboards-observability/common/query_manager/antlr/grammar/OpenSearchPPLLexer.g4 create mode 100644 dashboards-observability/common/query_manager/antlr/grammar/OpenSearchPPLParser.g4 create mode 100644 dashboards-observability/common/query_manager/antlr/ppl_syntax_parser.ts create mode 100644 dashboards-observability/common/query_manager/ast/builder/query_builder.ts create mode 100644 dashboards-observability/common/query_manager/ast/builder/stats_ast_builder.ts create mode 100644 dashboards-observability/common/query_manager/ast/builder/stats_builder.ts create mode 100644 dashboards-observability/common/query_manager/ast/expression/AggregateFunction.ts create mode 100644 dashboards-observability/common/query_manager/ast/expression/AggregateTerm.ts create mode 100644 dashboards-observability/common/query_manager/ast/expression/field.ts create mode 100644 dashboards-observability/common/query_manager/ast/expression/group_by.ts create mode 100644 dashboards-observability/common/query_manager/ast/expression/index.ts create mode 100644 dashboards-observability/common/query_manager/ast/expression/span.ts create mode 100644 dashboards-observability/common/query_manager/ast/expression/spanExpression.ts create mode 100644 dashboards-observability/common/query_manager/ast/index.ts create mode 100644 dashboards-observability/common/query_manager/ast/node.ts create mode 100644 dashboards-observability/common/query_manager/ast/tree/aggragations.ts create mode 100644 dashboards-observability/common/query_manager/ast/types/index.ts create mode 100644 dashboards-observability/common/query_manager/ast/types/stats.ts create mode 100644 dashboards-observability/common/query_manager/index.ts create mode 100644 dashboards-observability/common/query_manager/ppl_query_manager.ts create mode 100644 dashboards-observability/common/query_manager/query_builder/index.ts create mode 100644 dashboards-observability/common/query_manager/query_builder/ppl_query_builder.ts create mode 100644 dashboards-observability/common/query_manager/query_parser/index.ts create mode 100644 dashboards-observability/common/query_manager/query_parser/ppl_query_parser.ts create mode 100644 dashboards-observability/common/query_manager/utils/index.ts rename dashboards-observability/common/types/{app_analytics.ts => application_analytics.ts} (57%) create mode 100644 dashboards-observability/public/.DS_Store create mode 100644 dashboards-observability/public/components/application_analytics/components/flyout_components/availability_info_flyout.tsx delete mode 100644 dashboards-observability/public/components/application_analytics/helpers/types.tsx create mode 100644 dashboards-observability/public/components/common/helpers/delete_modal.tsx create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_bar_chart_styles.tsx create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_button_group.tsx create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_color_palette_picker.tsx create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_color_theme.tsx create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_heatmap_color_palette_picker.tsx create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_legend.tsx create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_line_chart_styles.tsx create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_logs_view.tsx create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_number_input.tsx create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_panel_option_gauge.tsx create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_single_color_picker.tsx create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_style_slider.tsx create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_switch.tsx create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_switch_button.tsx create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_tooltip.tsx create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/config_treemap_parents.tsx create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/data_config_panel_item.tsx create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/logs_view_config_panel_item.tsx create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/config_panel/config_panes/config_controls/treemap_config_panel_item.tsx create mode 100644 dashboards-observability/public/components/event_analytics/explorer/visualizations/shared_components/empty_placeholder.scss create mode 100644 dashboards-observability/public/components/visualizations/charts/__tests__/__snapshots__/histogram.test.tsx.snap create mode 100644 dashboards-observability/public/components/visualizations/charts/__tests__/__snapshots__/logs_view.test.tsx.snap create mode 100644 dashboards-observability/public/components/visualizations/charts/__tests__/__snapshots__/treemap.test.tsx.snap create mode 100644 dashboards-observability/public/components/visualizations/charts/__tests__/histogram.test.tsx create mode 100644 dashboards-observability/public/components/visualizations/charts/__tests__/logs_view.test.tsx create mode 100644 dashboards-observability/public/components/visualizations/charts/__tests__/treemap.test.tsx create mode 100644 dashboards-observability/public/components/visualizations/charts/data_table/data_table.scss create mode 100644 dashboards-observability/public/components/visualizations/charts/data_table/data_table_footer.tsx create mode 100644 dashboards-observability/public/components/visualizations/charts/data_table/data_table_header.tsx create mode 100644 dashboards-observability/public/components/visualizations/charts/logs_view/logs_view.scss create mode 100644 dashboards-observability/public/components/visualizations/charts/logs_view/logs_view.tsx create mode 100644 dashboards-observability/public/components/visualizations/charts/logs_view/logs_view_type.ts create mode 100755 opensearch-observability/scripts/build.sh create mode 100644 release-notes/opensearch-observability.release-notes-2.1.0.0.md create mode 100644 release-notes/opensearch-observability.release-notes-2.2.0.0.md diff --git a/.github/workflows/dashboards-observability-test-and-build-workflow.yml b/.github/workflows/dashboards-observability-test-and-build-workflow.yml index 608f6d1fb..7f09b560f 100644 --- a/.github/workflows/dashboards-observability-test-and-build-workflow.yml +++ b/.github/workflows/dashboards-observability-test-and-build-workflow.yml @@ -6,7 +6,7 @@ on: [pull_request, push] env: PLUGIN_NAME: dashboards-observability OPENSEARCH_VERSION: 'main' - OPENSEARCH_PLUGIN_VERSION: 2.0.0.0 + OPENSEARCH_PLUGIN_VERSION: 2.2.0.0 jobs: diff --git a/dashboards-observability/.cypress/integration/1_event_analytics.spec.js b/dashboards-observability/.cypress/integration/1_event_analytics.spec.js index 981b10b53..3f43a6eb7 100644 --- a/dashboards-observability/.cypress/integration/1_event_analytics.spec.js +++ b/dashboards-observability/.cypress/integration/1_event_analytics.spec.js @@ -17,10 +17,68 @@ import { landOnEventHome, landOnEventExplorer, landOnEventVisualizations, - landOnPanels + landOnPanels, + renderTreeMapchart, + renderPieChart, + renderLineChartForDataConfig, + renderDataConfig, + aggregationValues, + DataConfigLineChart, + renderAddParent, + renderGaugeChart, + renderAddParent } from '../utils/event_constants'; import { supressResizeObserverIssue } from '../utils/constants'; +const renderHistogramChart = () => { + querySearch(TEST_QUERIES[5].query, TEST_QUERIES[5].dateRangeDOM); + cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]').type('Histogram').type('{enter}'); + cy.wait(delay); + cy.get('g.draglayer.cursor-crosshair').should('exist'); + cy.get('#configPanel__panelOptions .euiFieldText').click().type('Histogram chart'); + cy.get('.euiFlexItem .euiFormRow [placeholder="Description"]').click().type('This is the description for Histogram chart'); + cy.get('.euiIEFlexWrapFix').eq(1).contains('Chart Styles').should('exist'); + cy.get('.euiFormLabel.euiFormRow__label').eq(2).contains('Bucket Size'); + cy.get('.euiFieldNumber').eq(0).type('4'); + cy.get('.euiFormLabel.euiFormRow__label').eq(3).contains('Bucket Offset'); + cy.get('.euiFieldNumber').eq(0).type('6'); +}; + +const vis_name_sub_string = Math.floor(Math.random() * 100); +const saveVisualizationAndVerify = () => { + cy.get('[data-test-subj="eventExplorer__saveManagementPopover"]').click(); + cy.get('[data-test-subj="eventExplorer__querySaveComboBox"]').click(); + cy.get('.euiComboBoxOptionsList__rowWrap .euiFilterSelectItem').eq(0).click(); + cy.get( + '.euiPopover__panel .euiFormControlLayoutIcons [data-test-subj="comboBoxToggleListButton"]' + ) + .eq(0) + .click(); + cy.get('.euiPopover__panel input') + .eq(1) + .type(`Test visualization` + vis_name_sub_string); + cy.get('[data-test-subj="eventExplorer__querySaveConfirm"]').click(); + cy.wait(delay); + cy.get('.euiHeaderBreadcrumbs a').eq(1).click(); + cy.get('.euiFlexGroup .euiFormControlLayout__childrenWrapper input') + .eq(0) + .type(`Test visualization` + vis_name_sub_string) + .type('{enter}'); + cy.get('.euiBasicTable .euiTableCellContent button').eq(0).click(); +}; +const deleteVisualization = () => { + cy.get('a[href = "#/event_analytics"]').click(); + cy.get('.euiFlexGroup .euiFormControlLayout__childrenWrapper input') + .eq(0) + .type(`Test visualization`) + .type('{enter}'); + cy.get('input[data-test-subj = "checkboxSelectAll"]').click(); + cy.get('.euiButtonContent.euiButtonContent--iconRight.euiButton__content').click(); + cy.get('.euiContextMenuItem .euiContextMenuItem__text').eq(0).click(); + cy.get('input[placeholder = "delete"]').clear().type('delete'); + cy.get('button[data-test-subj = "popoverModal__deleteButton"]').click(); + cy.get('.euiToastHeader').should('exist'); +}; describe('Adding sample data and visualization', () => { it('Adds sample flights data for event analytics', () => { cy.visit(`${Cypress.env('opensearchDashboards')}/app/home#/tutorial_directory/sampleData`); @@ -35,13 +93,13 @@ describe('Has working breadcrumbs', () => { it('Redirect to correct page on breadcrumb click', () => { landOnEventExplorer(); cy.wait(delay * 3); - cy.get('.euiBreadcrumb').contains('Explorer').click(); + cy.get('.euiBreadcrumb[href="#/event_analytics/explorer"]').contains('Explorer').click(); cy.wait(delay); cy.get('[data-test-subj="searchAutocompleteTextArea"]').should('exist'); - cy.get('.euiBreadcrumb').contains('Event analytics').click(); + cy.get('.euiBreadcrumb[href="#/event_analytics"]').contains('Event analytics').click(); cy.wait(delay); cy.get('.euiTitle').contains('Event analytics').should('exist'); - cy.get('.euiBreadcrumb').contains('Observability').click(); + cy.get('.euiBreadcrumb[href="observability-dashboards#/"]').contains('Observability').click(); cy.wait(delay); cy.get('.euiTitle').contains('Event analytics').should('exist'); }); @@ -55,11 +113,14 @@ describe('Search a query on event home', () => { cy.get('[data-test-subj="superDatePickerToggleQuickMenuButton"]').click(); cy.get('[data-test-subj="superDatePickerCommonlyUsed_Year_to date"]').click(); cy.get('[data-test-subj="superDatePickerApplyTimeButton"]').contains('Refresh').click(); - cy.window().its('store').invoke('getState').then((state) => { - expect(Object.values(state.queries)[0]['rawQuery'].trim()).equal(TEST_QUERIES[0].query) - expect(Object.values(state.queries)[0]['selectedDateRange'][0]).equal("now/y"); - expect(Object.values(state.queries)[0]['selectedDateRange'][1]).equal("now"); - }); + cy.window() + .its('store') + .invoke('getState') + .then((state) => { + expect(Object.values(state.queries)[0]['rawQuery'].trim()).equal(TEST_QUERIES[0].query); + expect(Object.values(state.queries)[0]['selectedDateRange'][0]).equal('now/y'); + expect(Object.values(state.queries)[0]['selectedDateRange'][1]).equal('now'); + }); cy.wait(delay); cy.url().should('contain', '#/event_analytics/explorer'); @@ -76,16 +137,26 @@ describe('Open flyout for a data row to see details', () => { it('Should be able to open flyout and see data, json and traces', () => { cy.get('[data-test-subj="docTable"] tbody tr button.euiButtonIcon').first().click(); cy.get('.observability-flyout').should('exist'); - cy.get('.observability-flyout .osdDocViewer .euiTabs span.euiTab__content').contains('JSON').click(); - cy.get('.observability-flyout .osdDocViewer .euiTabs span.euiTab__content').contains('Traces').click(); - cy.get('.observability-flyout .osdDocViewer .euiTabs span.euiTab__content').contains('Table').click(); + cy.get('.observability-flyout .osdDocViewer .euiTabs span.euiTab__content') + .contains('JSON') + .click(); + cy.get('.observability-flyout .osdDocViewer .euiTabs span.euiTab__content') + .contains('Traces') + .click(); + cy.get('.observability-flyout .osdDocViewer .euiTabs span.euiTab__content') + .contains('Table') + .click(); }); it('Should be able to see srrounding docs', () => { cy.get('[data-test-subj="docTable"] tbody tr button.euiButtonIcon').first().click(); cy.get('.observability-flyout').should('exist'); - cy.get('.observability-flyout span.euiButton__text').contains('View surrounding events').click(); - cy.get('.observability-flyout #surroundingFyout').contains('View surrounding events').should('exist'); + cy.get('.observability-flyout span.euiButton__text') + .contains('View surrounding events') + .click(); + cy.get('.observability-flyout #surroundingFyout') + .contains('View surrounding events') + .should('exist'); }); }); @@ -252,7 +323,9 @@ describe('Saves a query on explorer page', () => { cy.get('button[id="main-content-vis"]').contains('Visualizations').click(); cy.get('[data-test-subj="eventExplorer__saveManagementPopover"]').click(); cy.wait(delay * 2); - cy.get('[data-test-subj="eventExplorer__querySaveComboBox"] [data-test-subj="comboBoxToggleListButton"]').click(); + cy.get( + '[data-test-subj="eventExplorer__querySaveComboBox"] [data-test-subj="comboBoxToggleListButton"]' + ).click(); cy.get('[data-test-subj="eventExplorer__querySaveName"]').type(SAVE_QUERY2); cy.get('[data-test-subj="eventExplorer__querySaveConfirm"]').click(); cy.wait(delay * 2); @@ -282,11 +355,15 @@ describe('Saves a query on explorer page', () => { cy.get('button[id="main-content-vis"]').contains('Visualizations').click(); cy.get('[data-test-subj="eventExplorer__saveManagementPopover"]').click(); cy.wait(delay * 2); - cy.get('[data-test-subj="eventExplorer__querySaveComboBox"] [data-test-subj="comboBoxToggleListButton"]').click(); + cy.get( + '[data-test-subj="eventExplorer__querySaveComboBox"] [data-test-subj="comboBoxToggleListButton"]' + ).click(); cy.get('[data-test-subj="eventExplorer__querySaveName"]').type(SAVE_QUERY3); cy.get('[data-test-subj="eventExplorer__querySaveComboBox"]').type(TESTING_PANEL); cy.get(`input[value="${TESTING_PANEL}"]`).click(); - cy.get('[data-test-subj="eventExplorer__querySaveComboBox"] [data-test-subj="comboBoxToggleListButton"]').click(); + cy.get( + '[data-test-subj="eventExplorer__querySaveComboBox"] [data-test-subj="comboBoxToggleListButton"]' + ).click(); cy.get('[data-test-subj="eventExplorer__querySaveConfirm"]').click(); cy.wait(delay); @@ -305,8 +382,11 @@ describe('Override timestamp for an index', () => { cy.wait(delay); cy.get('[data-attr-field="utc_time"] [data-test-subj="eventFields__default-timestamp-mark"') - .contains('Default Timestamp').should('exist'); - cy.get('[data-attr-field="timestamp"] [data-test-subj="eventFields__default-timestamp-mark"').should('not.exist'); + .contains('Default Timestamp') + .should('exist'); + cy.get( + '[data-attr-field="timestamp"] [data-test-subj="eventFields__default-timestamp-mark"' + ).should('not.exist'); }); }); @@ -369,20 +449,40 @@ describe('Click to view field insights', () => { it('Click a numerical field to view field insights', () => { cy.get('[data-test-subj="field-bytes-showDetails"]').click(); - cy.get('[data-test-subj="sidebarField__fieldInsights"] button').contains('Top values').should('exist'); - cy.get('[data-test-subj="sidebarField__fieldInsights"] button').contains('Rare values').should('exist'); - cy.get('[data-test-subj="sidebarField__fieldInsights"] button').contains('Average overtime').should('exist'); - cy.get('[data-test-subj="sidebarField__fieldInsights"] button').contains('Maximum overtime').should('exist'); - cy.get('[data-test-subj="sidebarField__fieldInsights"] button').contains('Minimum overtime').should('exist'); + cy.get('[data-test-subj="sidebarField__fieldInsights"] button') + .contains('Top values') + .should('exist'); + cy.get('[data-test-subj="sidebarField__fieldInsights"] button') + .contains('Rare values') + .should('exist'); + cy.get('[data-test-subj="sidebarField__fieldInsights"] button') + .contains('Average overtime') + .should('exist'); + cy.get('[data-test-subj="sidebarField__fieldInsights"] button') + .contains('Maximum overtime') + .should('exist'); + cy.get('[data-test-subj="sidebarField__fieldInsights"] button') + .contains('Minimum overtime') + .should('exist'); }); it('Click a non-numerical field to view insights', () => { cy.get('[data-test-subj="field-host-showDetails"]').click(); - cy.get('[data-test-subj="sidebarField__fieldInsights"] button').contains('Top values').should('exist'); - cy.get('[data-test-subj="sidebarField__fieldInsights"] button').contains('Rare values').should('exist'); - cy.get('[data-test-subj="sidebarField__fieldInsights"] button').contains('Average overtime').should('not.exist'); - cy.get('[data-test-subj="sidebarField__fieldInsights"] button').contains('Maximum overtime').should('not.exist'); - cy.get('[data-test-subj="sidebarField__fieldInsights"] button').contains('Minimum overtime').should('not.exist'); + cy.get('[data-test-subj="sidebarField__fieldInsights"] button') + .contains('Top values') + .should('exist'); + cy.get('[data-test-subj="sidebarField__fieldInsights"] button') + .contains('Rare values') + .should('exist'); + cy.get('[data-test-subj="sidebarField__fieldInsights"] button') + .contains('Average overtime') + .should('not.exist'); + cy.get('[data-test-subj="sidebarField__fieldInsights"] button') + .contains('Maximum overtime') + .should('not.exist'); + cy.get('[data-test-subj="sidebarField__fieldInsights"] button') + .contains('Minimum overtime') + .should('not.exist'); }); }); @@ -426,8 +526,8 @@ describe('Live tail stop automatically', () => { cy.get('[data-test-subj="eventExplorer__topLevelTabbing"]') .find('button.euiTab') .should('have.length', initialLength + 1); + }); }); -}); it('Click to switch to another tab', () => { cy.get('[data-test-subj="eventExplorer__addNewTab"]').click(); @@ -469,7 +569,9 @@ describe('Renders noresult chart', () => { }); it('It should render no result when there is no data', () => { - cy.get('[data-test-subj="vizWorkspace__noData"] p').contains('No results found').should('exist'); + cy.get('[data-test-subj="vizWorkspace__noData"] p') + .contains('No results found') + .should('exist'); }); }); @@ -480,7 +582,9 @@ describe('Renders bar charts', () => { it('Renders vertical bar chart', () => { querySearch(TEST_QUERIES[3].query, TEST_QUERIES[3].dateRangeDOM); - cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]').click(); + cy.get( + '[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]' + ).click(); cy.wait(delay * 2); cy.get('[data-test-subj="comboBoxOptionsList "] span').contains('Bar').click(); cy.get('#configPanel__value_options [data-test-subj="comboBoxInput"]').first().click(); @@ -497,12 +601,16 @@ describe('Renders bar charts', () => { cy.get('[data-test-subj="comboBoxOptionsList "] button span').contains('Group').click(); cy.get('[data-test-subj="visualizeEditorRenderButton"]').click(); cy.wait(delay * 2); - cy.get('g.xaxislayer-above > g.xtick text[data-unformatted|="artifacts.opensearch.org"]').should('exist'); + cy.get( + 'g.xaxislayer-above > g.xtick text[data-unformatted|="artifacts.opensearch.org"]' + ).should('exist'); }); it('Renders horiztontal bar chart', () => { querySearch(TEST_QUERIES[3].query, TEST_QUERIES[3].dateRangeDOM); - cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]').click(); + cy.get( + '[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]' + ).click(); cy.wait(delay * 2); cy.get('[data-test-subj="comboBoxOptionsList "] button span').contains('Bar').click(); cy.get('#configPanel__value_options [data-test-subj="comboBoxInput"]').first().click(); @@ -519,7 +627,9 @@ describe('Renders bar charts', () => { cy.get('[data-test-subj="comboBoxOptionsList "] button span').contains('Group').click(); cy.get('[data-test-subj="visualizeEditorRenderButton"]').click(); cy.wait(delay * 2); - cy.get('g.yaxislayer-above > g.ytick text[data-unformatted|="artifacts.opensearch.org"]').should('exist'); + cy.get( + 'g.yaxislayer-above > g.ytick text[data-unformatted|="artifacts.opensearch.org"]' + ).should('exist'); }); }); @@ -530,7 +640,9 @@ describe('Renders line charts', () => { it('Renders line chart with threshold', () => { querySearch(TEST_QUERIES[3].query, TEST_QUERIES[3].dateRangeDOM); - cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]').click(); + cy.get( + '[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]' + ).click(); cy.get('[data-test-subj="comboBoxOptionsList "] button span').contains('Line').click(); cy.get('#configPanel__value_options [data-test-subj="comboBoxInput"]').first().click(); cy.get('[data-test-subj="comboBoxOptionsList "] button span').contains('host').click(); @@ -544,7 +656,9 @@ describe('Renders line charts', () => { cy.get('[data-test-subj="visualizeEditorRenderButton"]').click(); cy.wait(delay * 2); cy.get('g.text > g.textpoint text[data-unformatted|="Max"]').should('exist'); - cy.get('g.xaxislayer-above > g.xtick text[data-unformatted|="artifacts.opensearch.org"]').should('exist'); + cy.get( + 'g.xaxislayer-above > g.xtick text[data-unformatted|="artifacts.opensearch.org"]' + ).should('exist'); }); }); @@ -555,7 +669,9 @@ describe('Renders pie charts', () => { it('Renders pie chart', () => { querySearch(TEST_QUERIES[3].query, TEST_QUERIES[3].dateRangeDOM); - cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]').click(); + cy.get( + '[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]' + ).click(); cy.get('[data-test-subj="comboBoxOptionsList "] button span').contains('Pie').click(); cy.wait(delay); cy.get('g.pielayer').should('exist'); @@ -569,7 +685,9 @@ describe('Renders heatmap chart', () => { it('Renders heatmap chart with different z-axes', () => { querySearch(TEST_QUERIES[4].query, TEST_QUERIES[4].dateRangeDOM); - cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]').click(); + cy.get( + '[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]' + ).click(); cy.get('[data-test-subj="comboBoxOptionsList "] button span').contains('Heatmap').click(); cy.wait(delay * 2); cy.get('#configPanel__value_options [data-test-subj="comboBoxInput"]').click(); @@ -593,13 +711,17 @@ describe('Renders markdown chart', () => { it('Renders markdown chart with test title', () => { querySearch(TEST_QUERIES[3].query, TEST_QUERIES[3].dateRangeDOM); - cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]').click(); + cy.get( + '[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]' + ).click(); cy.get('[data-test-subj="comboBoxOptionsList "] button span').contains('Text').click(); cy.get('[data-test-subj="workspace__viz_markdown"] h2').contains('Text').should('exist'); cy.get('textarea.euiMarkdownEditorTextArea').type('## testing title'); cy.get('[data-test-subj="visualizeEditorRenderButton"]').click(); cy.wait(delay * 2); - cy.get('[data-test-subj="workspace__viz_markdown"] h2').contains('testing title').should('exist'); + cy.get('[data-test-subj="workspace__viz_markdown"] h2') + .contains('testing title') + .should('exist'); }); }); @@ -615,4 +737,302 @@ describe('Renders data view', () => { cy.get('[data-test-subj="workspace__dataTableViewSwitch"]').click(); cy.get('[data-test-subj="workspace__dataTable"]').should('not.exist'); }); -}); \ No newline at end of file +}); + +describe('Renders chart and verify Toast message if X-axis and Y-axis values are empty', () => { + beforeEach(() => { + landOnEventVisualizations(); + }); + it('Renders chart, clear X-axis and Y-axis value and click on Apply button, Toast message should display with error message', () => { + querySearch(TEST_QUERIES[4].query, TEST_QUERIES[4].dateRangeDOM); + cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]') + .type('Bar') + .type('{enter}'); + cy.wait(delay); + cy.get('#configPanel__value_options [data-test-subj="comboBoxClearButton"]') + .eq(0) + .click({ force: true }); + cy.get('#configPanel__value_options [data-test-subj="comboBoxToggleListButton"]').eq(0).click(); + cy.wait(delay); + cy.get('#configPanel__value_options [data-test-subj="comboBoxClearButton"]').click({ + multiple: true, + }); + cy.get('#configPanel__value_options [data-test-subj="comboBoxToggleListButton"]').eq(1).click(); + cy.get('#configPanel__value_options [data-test-subj="comboBoxInput"]') + .eq(0) + .should('have.value', ''); + cy.get('#configPanel__value_options [data-test-subj="comboBoxInput"]') + .eq(1) + .should('have.value', ''); + cy.get('[data-test-subj="visualizeEditorRenderButton"]').click(); + cy.get('[data-test-subj="euiToastHeader"]') + .contains('Invalid value options configuration selected.') + .should('exist'); + }); + + it('Renders chart, clear X-axis and Y-axis value and try to save visulization, Toast message should display with error message', () => { + querySearch(TEST_QUERIES[4].query, TEST_QUERIES[4].dateRangeDOM); + cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]') + .type('Bar') + .type('{enter}'); + cy.wait(delay); + cy.get('#configPanel__value_options [data-test-subj="comboBoxClearButton"]') + .eq(0) + .click({ force: true }); + cy.get('#configPanel__value_options [data-test-subj="comboBoxToggleListButton"]').eq(0).click(); + cy.wait(delay); + cy.get('#configPanel__value_options [data-test-subj="comboBoxClearButton"]').click({ + multiple: true, + }); + cy.get('#configPanel__value_options [data-test-subj="comboBoxInput"]') + .eq(0) + .should('have.value', ''); + cy.get('#configPanel__value_options [data-test-subj="comboBoxInput"]') + .eq(1) + .should('have.value', ''); + cy.get('[data-test-subj="eventExplorer__saveManagementPopover"]').click(); + cy.get('[data-test-subj="eventExplorer__querySaveComboBox"]').click(); + cy.get('.euiComboBoxOptionsList__rowWrap .euiFilterSelectItem').eq(0).click(); + cy.get( + '.euiPopover__panel .euiFormControlLayoutIcons [data-test-subj="comboBoxToggleListButton"]' + ) + .eq(0) + .click(); + cy.get('.euiPopover__panel input').eq(1).type(`Test visulization_`); + cy.get('[data-test-subj="eventExplorer__querySaveConfirm"]').click(); + cy.get('[data-test-subj="euiToastHeader"]') + .contains('Invalid value options configuration selected.') + .should('exist'); + }); +}); + +describe('Render Table View', () => { + beforeEach(() => { + landOnEventVisualizations(); + querySearch(TEST_QUERIES[3].query, TEST_QUERIES[3].dateRangeDOM); + cy.get('[data-test-subj="workspace__dataTableViewSwitch"]').click(); + }); + + it('Switch visualization for table view and verify table data', () => { + cy.get('.ag-header-cell-text').contains('max(AvgTicketPrice)').should('exist'); + cy.get('.ag-header-cell-text').contains('DestCountry').should('exist'); + cy.get('.ag-header-cell-text').contains('DestCityName').should('exist'); + cy.get('.ag-header-cell-text').contains('Carrier').should('exist'); + }); + + it('Switch visualization for table view and change data table density', () => { + cy.get('.euiButtonEmpty__text').contains('Density').click(); + cy.get('.euiButtonIcon.euiButtonIcon--primary.euiButtonIcon--xSmall').eq(1).click(); + cy.get('.euiButtonIcon.euiButtonIcon--primary.euiButtonIcon--xSmall').eq(2).click(); + }); + + it('Switch visualization for table view and show and hide column', () => { + cy.get('.euiButtonEmpty__text').contains('Columns').click(); + cy.get('.euiSwitch__label').contains('DestCountry').click(); + cy.get('.ag-header-cell-text').contains('DestCountry').should('not.exist'); + cy.get('.euiSwitch__label').contains('Carrier').click(); + cy.get('.ag-header-cell-text').contains('Carrier').should('not.exist'); + cy.get('.euiSwitch__label').contains('DestCountry').click(); + cy.get('.ag-header-cell-text').contains('DestCountry').should('exist'); + }); + + it('Switch visualization for table view and see data in full screen', () => { + cy.get('.ag-header-cell-text').contains('max(AvgTicketPrice)').should('exist'); + cy.get('.ag-header-cell-text').contains('DestCountry').should('exist'); + cy.get('.ag-header-cell-text').contains('DestCityName').should('exist'); + cy.get('.ag-header-cell-text').contains('Carrier').should('exist'); + cy.get('.euiButtonEmpty__text').contains('Full screen').click(); + cy.wait(delay); + cy.get('body').type('{esc}'); + cy.wait(delay); + }); + + it('Switch visualization for table view and sort the column data', () => { + cy.get('.ag-header-cell-text').contains('max(AvgTicketPrice)').click(); + cy.get('.ag-cell-value').contains('125.49737').should('exist'); + cy.get('.ag-header-cell-text').contains('max(AvgTicketPrice)').click(); + cy.get('.ag-cell-value').contains('1199.729').should('exist'); + cy.get('.ag-header-cell-text').contains('DestCountry').click(); + cy.get('.ag-cell-value').contains('AE').should('exist'); + }); + + it('Switch visualization for table view and verify pagination link', () => { + cy.get('[aria-label="Next page"]').click(); + cy.get('.ag-cell-value').contains('Vienna').should('exist'); + cy.get('[aria-label="Previous page"]').click(); + cy.get('.ag-cell-value').contains('Dubai').should('exist'); + cy.get('[aria-label="Page 4"]').contains('4').click(); + cy.get('.ag-cell-value').contains('Edmonton').should('exist'); + }); + it('Switch visualization for table view and rows per page data', () => { + cy.get('.euiButtonEmpty__text').eq('6').click(); + cy.get('.euiContextMenuItem__text').eq(1).click(); + }); +}); + +describe('Render Time series chart/Line chart and verify Data configurations UI ', () => { + it('Render line chart and verify Data Configuration Panel', () => { + renderLineChartForDataConfig(); + DataConfigLineChart(); + }); +}); + +describe('Renders Data Configurations section for Pie chart', () => { + beforeEach(() => { + landOnEventVisualizations(); + }); + + it('Renders Dimensions and Metrics under Data Configurations for Pie chart', () => { + renderPieChart(); + renderDataConfig(); + }); + + it('Validate "Add" and "X" buttons', () => { + renderPieChart(); + cy.get('.euiResizablePanel.euiResizablePanel--middle').contains('Data Configurations'); + cy.get('.euiButton.euiButton--primary.euiButton--fullWidth').contains('Add').click(); + cy.get('.euiFormRow__fieldWrapper .euiComboBox').eq(3).click(); + cy.get('.euiComboBoxOption__content').eq(2).click(); + cy.get('.first-division .euiFormLabel.euiFormRow__label').eq(4).click(); + cy.get('.euiComboBoxOption__content').eq(1).click(); + cy.get('.euiFieldText[placeholder="Custom label"]').eq(1).type('Demo field'); + cy.get('.euiIcon.euiIcon--medium.euiIcon--danger').eq(1).click(); + cy.get('.euiButton.euiButton--primary.euiButton--fullWidth').contains('Add').should('exist'); + }); + + it('Verify drop down values for Aggregation', () => { + renderPieChart(); + cy.get('.euiResizablePanel.euiResizablePanel--middle').contains('Data Configurations'); + cy.get('.euiTitle.euiTitle--xxsmall').eq(1).contains('Dimensions').should('exist'); + cy.get('.first-division .euiFormLabel.euiFormRow__label').eq(0).contains('Aggregation'); + cy.get('[data-test-subj="comboBoxSearchInput"]').eq(0).click(); + aggregationValues.forEach(function (value){ + cy.get('.euiComboBoxOption__content').contains(value); + }); + }); + + it('Collapsible mode for Data Configuration panel', () => { + renderPieChart(); + cy.get('.euiResizablePanel.euiResizablePanel--middle').contains('Data Configurations'); + cy.get('.euiResizableButton.euiResizableButton--horizontal').eq(1).click(); + cy.get('[data-test-subj="panel-1-toggle"]').click(); + cy.get('[class*="euiResizableToggleButton-isCollapsed"]').eq(1).should('exist'); +describe('Renders Histogram chart', () => { + beforeEach(() => { + landOnEventVisualizations(); +}); + +it('Renders Histogram chart and save visualization', () => { + renderHistogramChart(); + cy.get('.euiFlexItem.euiFlexItem--flexGrowZero .euiButton__text').eq(2).click(); + cy.wait(delay); + saveVisualizationAndVerify(); + }); + + it('Delete Visualization for Histogram chart from list of saved Visualizations on Event analytics page', () =>{ + deleteVisualization(); + }) + + it('Renders Histogram chart, add value parameters and verify Reset button click is working', () => { + renderHistogramChart(); + cy.get('[data-test-subj="visualizeEditorResetButton"]').click(); + }); +}); +describe('Render Gauge Chart and verify if data gets render', () => { + it('Render gauge chart and verify by default no data gets render', () => { + renderGaugeChart(); + cy.get('.main-svg').contains('BeatsWest').should('not.exist'); + }); + + it('Render gauge chart and verify data gets render after click on update chart', () => { + renderGaugeChart(); + cy.get('.euiButton__text').contains('Update chart').click(); + cy.get('.main-svg').contains('BeatsWest').should('exist'); + }); +}); + +describe('Render Gauge Chart and work with chart styles', () => { + it('Render gauge chart and change orientation to vertical', () => { + renderGaugeChart(); + cy.get('.euiButton__text').contains('Update chart').click(); + cy.get('.euiButton__text').contains('Vertical').click(); + cy.get('.euiButton__text').contains('Preview').click(); + }); + + it('Render gauge chart and change title size then verify the update on chart', () => { + renderGaugeChart(); + cy.get('.euiButton__text').contains('Update chart').click(); + cy.get('[data-test-subj="valueFieldNumber"]').eq(0).click(); + cy.get('[data-test-subj="valueFieldNumber"]').eq(0).type('30'); + cy.get('.euiButton__text').contains('Preview').click(); + }); + + it('Render gauge chart and change value size then verify the update on chart', () => { + renderGaugeChart(); + cy.get('.euiButton__text').contains('Update chart').click(); + cy.get('[data-test-subj="valueFieldNumber"]').eq(1).click(); + cy.get('[data-test-subj="valueFieldNumber"]').eq(1).type('20'); + cy.get('.euiButton__text').contains('Preview').click(); + }); +}); + +describe('Render Gauge Chart and work with threshold', () => { + it('Render gauge chart and add threshold then verify by default the threshold is not seen', () => { + renderGaugeChart(); + cy.get('.euiButton__text').contains('Update chart').click(); + cy.get('.euiButton__text').contains('+ Add threshold').click(); + cy.get('[data-test-subj="nameFieldText"]').type('Gauge Threshold'); + cy.get('[data-test-subj="valueFieldNumber"]').eq(2).type('50'); + cy.get('.euiButton__text').contains('Preview').click(); + cy.get('[data-unformatted="Gauge Threshold"]').should('not.be.visible'); + }); + + it('Render gauge chart and add threshold then verify the threshold label are seen after show threshold button enabled ', () => { + renderGaugeChart(); + cy.get('.euiButton__text').contains('Update chart').click(); + cy.get('.euiButton__text').contains('+ Add threshold').click(); + cy.get('[data-test-subj="nameFieldText"]').type('Gauge Threshold'); + cy.get('[data-test-subj="valueFieldNumber"]').eq(2).type('50'); + cy.get('.euiSwitch__label').contains('Show threshold labels').click(); + cy.get('.euiButton__text').contains('Preview').click(); + cy.get('[data-unformatted="Gauge Threshold"]').should('be.visible'); + }); + + it('Render gauge chart and add threshold then verify the threshold marker are seen after show threshold button enabled ', () => { + renderGaugeChart(); + cy.get('.euiButton__text').contains('Update chart').click(); + cy.get('.euiButton__text').contains('+ Add threshold').click(); + cy.get('[data-test-subj="nameFieldText"]').type('Gauge Threshold'); + cy.get('[data-test-subj="valueFieldNumber"]').eq(2).type('50'); + cy.get('.euiSwitch__label').contains('Show threshold markers').click(); + cy.get('.euiButton__text').contains('Preview').click(); + cy.get('path[style*="rgb(252, 5, 5)"]').eq(1).should('exist'); + cy.get('.bg-arc').find('path[style*="rgb(252, 5, 5)"]').should('have.length',4); + }); +}); + +describe('Render gauge chart and verify if reset works properly', () => { + it('Render gauge chart with all feild data then click on reset and verify reset works properly', () => { + renderGaugeChart(); + cy.get('.euiButton__text').contains('Update chart').click(); + cy.get('input[placeholder="Title"]').type('Gauge Chart'); + cy.get('textarea[placeholder="Description"]').type('Description For Gauge Chart'); + cy.get('.euiButton__text').contains('Vertical').click(); + cy.get('[data-test-subj="valueFieldNumber"]').eq(0).click(); + cy.get('[data-test-subj="valueFieldNumber"]').eq(0).type('30'); + cy.get('[data-test-subj="valueFieldNumber"]').eq(1).click(); + cy.get('[data-test-subj="valueFieldNumber"]').eq(1).type('20'); + cy.get('.euiButton__text').contains('+ Add threshold').click(); + cy.get('[data-test-subj="nameFieldText"]').type('Gauge Threshold'); + cy.get('[data-test-subj="valueFieldNumber"]').eq(2).type('50'); + cy.get('.euiSwitch__label').contains('Show threshold labels').click(); + cy.get('.euiSwitch__label').contains('Show threshold markers').click(); + cy.get('.euiButton__text').contains('Preview').click(); + cy.get('.euiButtonEmpty__text').contains('Reset').click(); + cy.get('input[placeholder="Title"]').should('not.have.value','Gauge Chart'); + cy.get('textarea[placeholder="Description"]').should('not.have.value','Description For Gauge Chart') + cy.get('[data-test-subj="valueFieldNumber"]').eq(0).should('have.value',''); + cy.get('[data-test-subj="valueFieldNumber"]').eq(1).should('have.value',''); + cy.get('button.euiSwitch__button[aria-checked="false"]').should('exist').should('have.length',3); + }); +}); diff --git a/dashboards-observability/.cypress/integration/2_notebooks.spec.js b/dashboards-observability/.cypress/integration/2_notebooks.spec.js index ca0083249..3ba071215 100644 --- a/dashboards-observability/.cypress/integration/2_notebooks.spec.js +++ b/dashboards-observability/.cypress/integration/2_notebooks.spec.js @@ -12,6 +12,8 @@ import { SAMPLE_URL, SQL_QUERY_TEXT, PPL_QUERY_TEXT, + NOTEBOOK_TEXT, + OPENSEARCH_URL, } from '../utils/constants'; import { SAMPLE_PANEL } from '../utils/panel_constants'; @@ -63,6 +65,13 @@ describe('Testing notebooks table', () => { cy.visit(`${Cypress.env('opensearchDashboards')}/app/observability-dashboards#/notebooks`); }); + it('Notebooks table empty state', () => { + cy.get('#notebookArea').contains('Notebooks (0)').should('exist'); + cy.get('.euiTextAlign.euiTextAlign--center').contains('No notebooks'); + cy.get('.euiButton__text').eq(2).contains('Create notebook'); + cy.get('.euiButton__text').eq(3).contains('Add samples'); + }); + it('Displays error toast for invalid notebook name', () => { cy.get('.euiButton__text').contains('Create notebook').click(); cy.wait(delay); @@ -125,6 +134,21 @@ describe('Testing notebooks table', () => { .should('exist'); }); + it('Notebooks table columns headers and pagination', () => { + cy.get('.euiTitle.euiTitle--small').contains('Notebooks').should('exist'); + cy.get('.euiTableCellContent__text[title="Name"]').should('exist'); + cy.get('.euiTableCellContent__text[title="Last updated"]').should('exist'); + cy.get('.euiTableCellContent__text[title="Created"]').should('exist'); + cy.get('[data-test-subj="tablePaginationPopoverButton"]').should('exist'); + }); + + it('"Learn more" link under Notebooks header', () => { + cy.get('.euiTitle.euiTitle--small').contains('Notebooks'); + cy.get('.euiTextColor.euiTextColor--subdued').contains(NOTEBOOK_TEXT); + cy.get('a.euiLink.euiLink--primary').contains('Learn more').click(); + cy.get(`a[href="${OPENSEARCH_URL}"]`).should('exist'); + }); + it('Deletes notebooks', () => { cy.get('.euiCheckbox__input[data-test-subj="checkboxSelectAll"]').click(); cy.wait(delay); @@ -231,6 +255,16 @@ describe('Testing paragraphs', () => { cy.get('.euiTitle').contains('Event analytics').should('exist'); }); + it('Paragraph actions layout', () => { + cy.get('button[data-test-subj="notebook-paragraph-actions-button"]').should('exist').click(); + cy.get('.euiContextMenuPanelTitle').contains('Actions'); + cy.get('.euiContextMenuItem__text').eq(0).contains('Add paragraph to top'); + cy.get('.euiContextMenuItem__text').eq(1).contains('Add paragraph to bottom'); + cy.get('.euiContextMenuItem__text').eq(2).contains('Run all paragraphs'); + cy.get('.euiContextMenuItem__text').eq(3).contains('Clear all outputs'); + cy.get('.euiContextMenuItem__text').eq(4).contains('Delete all paragraphs'); + }); + it('Renders markdown', () => { cy.get('.euiTextArea').should('not.exist'); cy.get(`a[href="${SAMPLE_URL}"]`).should('exist'); diff --git a/dashboards-observability/.cypress/integration/4_trace_analytics_dashboard.spec.js b/dashboards-observability/.cypress/integration/4_trace_analytics_dashboard.spec.js index 6e510a8d8..f9bfb5760 100644 --- a/dashboards-observability/.cypress/integration/4_trace_analytics_dashboard.spec.js +++ b/dashboards-observability/.cypress/integration/4_trace_analytics_dashboard.spec.js @@ -187,3 +187,108 @@ describe('Testing plots', () => { cy.get('text.annotation-text[data-unformatted="Now: 108"]').should('exist'); }); }); + +describe('Latency by trace group table', () =>{ + beforeEach(() => { + cy.visit('app/observability-dashboards#/trace_analytics/home', { + onBeforeLoad: (win) => { + win.sessionStorage.clear(); + }, + }); + setTimeFilter(); + }); + + it('Verify columns in Latency by trace group table along with pagination functionality', () => { + cy.get('span.panel-title').eq(0).should('exist'); + cy.wait(delay); + cy.get('span[title="Trace group name"]').should('exist'); + cy.get('span[title="Latency variance (ms)"]').should('exist'); + cy.get('span[title="Average latency (ms)"]').should('exist'); + cy.get('span[title="24-hour latency trend"]').should('exist'); + cy.get('span[title="Error rate"] .euiToolTipAnchor').should('exist'); + cy.get('span[title="Traces"] .euiToolTipAnchor').should('exist'); + cy.get('[data-test-subj="tablePaginationPopoverButton"]').click(); + cy.get('.euiIcon.euiIcon--medium.euiIcon--inherit.euiContextMenu__icon').eq(0).should('exist').click(); + cy.get('[data-test-subj="pagination-button-next"]').should('exist').click(); + cy.get('button[data-test-subj="dashboard-table-trace-group-name-button"]').contains('mysql').should('exist'); + }); + + it('Sorts the Latency by trace group table', () => { + cy.get('span[title*="Trace group name"]').click(); + cy.get('[data-test-subj="dashboard-table-trace-group-name-button"]').eq(0).contains('/**').should('exist'); + cy.wait(delay); + }); + + it('Verify tooltips in Latency by trace group table', () => { + cy.get('.euiIcon.euiIcon--small.euiIcon--subdued.euiIcon-isLoaded.eui-alignTop').eq(0).trigger('mouseover'); + cy.contains('Traces of all requests that share a common API and operation at the start of distributed tracing instrumentation.').should('be.visible'); + cy.get('.euiIcon.euiIcon--small.euiIcon--subdued.euiIcon-isLoaded.eui-alignTop').eq(1).trigger('mouseover'); + cy.contains('Range of latencies for traces within a trace group in the selected time range.').should('be.visible'); + cy.get('.euiIcon.euiIcon--small.euiIcon--subdued.euiIcon-isLoaded.eui-alignTop').eq(2).trigger('mouseover'); + cy.contains('Average latency of traces within a trace group in the selected time range.').should('be.visible'); + cy.get('.euiIcon.euiIcon--small.euiIcon--subdued.euiIcon-isLoaded.eui-alignTop').eq(3).trigger('mouseover'); + cy.contains('24 hour time series view of hourly average, hourly percentile, and hourly range of latency for traces within a trace group.').should('be.visible'); + cy.get('.euiIcon.euiIcon--small.euiIcon--subdued.euiIcon-isLoaded.eui-alignTop').eq(4).trigger('mouseover'); + cy.contains('Error rate based on count of trace errors within a trace group in the selected time range.').should('be.visible'); + cy.get('.euiIcon.euiIcon--small.euiIcon--subdued.euiIcon-isLoaded.eui-alignTop').eq(5).trigger('mouseover'); + cy.contains('Count of traces with unique trace identifiers in the selected time range.').should('be.visible'); + }); + + it('Verify Search engine on Trace dashboard', () => { + cy.get('.euiFieldSearch.euiFieldSearch--fullWidth').click().type('client_pay_order{enter}'); + cy.wait(delay); + cy.get('.euiTableCellContent.euiTableCellContent--alignRight.euiTableCellContent--overflowingContent').contains('211.04').should('exist'); + cy.get('button[data-test-subj="dashboard-table-trace-group-name-button"]').click(); + cy.get('.euiBadge.euiBadge--hollow.euiBadge--iconRight.globalFilterItem').click(); + cy.get('.euiIcon.euiIcon--medium.euiContextMenu__arrow').click(); + cy.get('.euiContextMenuPanelTitle').contains('Edit filter').should('exist'); + cy.get('.euiButton.euiButton--primary.euiButton--fill').click(); + cy.get('.euiBadge.euiBadge--hollow.euiBadge--iconRight.globalFilterItem').click(); + cy.get('.euiContextMenuItem__text').eq(1).contains('Exclude results').click(); + cy.get('.euiTextColor.euiTextColor--danger').should('exist'); + cy.get('.euiBadge.euiBadge--hollow.euiBadge--iconRight.globalFilterItem').click(); + cy.get('.euiContextMenuItem__text').eq(1).contains('Include results').click(); + cy.get('.euiBadge.euiBadge--hollow.euiBadge--iconRight.globalFilterItem').click(); + cy.get('.euiContextMenuItem__text').eq(2).contains('Temporarily disable').click(); + cy.get('.euiBadge.euiBadge--iconRight.globalFilterItem.globalFilterItem-isDisabled').should('exist').click(); + cy.get('.euiContextMenuItem__text').eq(2).contains('Re-enable').click(); + cy.get('.euiBadge.euiBadge--hollow.euiBadge--iconRight.globalFilterItem').click(); + cy.get('.euiContextMenuItem__text').eq(3).contains('Delete').click(); + }); +}); + +describe('Testing filters on trace analytics page', () =>{ + beforeEach(() => { + cy.visit('app/observability-dashboards#/trace_analytics/home', { + onBeforeLoad: (win) => { + win.sessionStorage.clear(); + }, + }); + setTimeFilter(); + }); + + it('Verify Change all filters', () =>{ + cy.get('.euiButtonIcon.euiButtonIcon--primary.euiButtonIcon--empty.euiButtonIcon--xSmall').click(); + cy.get('.euiContextMenuPanelTitle').contains('Change all filters').should('exist'); + cy.get('.euiContextMenuItem__text').eq(0).contains('Enable all'); + cy.get('.euiContextMenuItem__text').eq(1).contains('Disable all'); + cy.get('.euiContextMenuItem__text').eq(2).contains('Invert inclusion'); + cy.get('.euiContextMenuItem__text').eq(3).contains('Invert enabled/disabled'); + cy.get('.euiContextMenuItem__text').eq(4).contains('Remove all'); + }) + + it('Verify Add filter section', () => { + cy.get('.euiPopover.euiPopover--anchorDownLeft').contains('+ Add filter').click(); + cy.get('.euiPopoverTitle').contains('Add filter').should('exist'); + cy.wait(delay); + cy.get('.euiComboBox__inputWrap.euiComboBox__inputWrap--noWrap').eq(0).trigger('mouseover').click(); + cy.get('.euiComboBoxOption__content').eq(1).click(); + cy.get('.euiComboBox__inputWrap.euiComboBox__inputWrap--noWrap').eq(1).trigger('mouseover').click(); + cy.get('.euiComboBoxOption__content').eq(2).click(); + cy.get('.euiButton.euiButton--primary.euiButton--fill').contains('Save').click(); + cy.get('.euiBadge__content').should('exist').click(); + cy.get('.euiIcon.euiIcon--medium.euiContextMenu__arrow').click(); + cy.get('[data-test-subj="filter-popover-cancel-button"]').contains('Cancel').click(); + cy.get('.euiIcon.euiIcon--small.euiIcon--inherit.euiBadge__icon').click(); + }) +}); diff --git a/dashboards-observability/.cypress/integration/5_trace_analytics_services.spec.js b/dashboards-observability/.cypress/integration/5_trace_analytics_services.spec.js index b03e10e64..bd2cd4c41 100644 --- a/dashboards-observability/.cypress/integration/5_trace_analytics_services.spec.js +++ b/dashboards-observability/.cypress/integration/5_trace_analytics_services.spec.js @@ -5,7 +5,7 @@ /// -import { delay, SERVICE_NAME, SERVICE_SPAN_ID, setTimeFilter } from '../utils/constants'; +import { delay, SERVICE_NAME, SERVICE_SPAN_ID, setTimeFilter, verify_traces_spans_data_grid_cols_exists, count_table_row } from '../utils/constants'; describe('Testing services table empty state', () => { beforeEach(() => { @@ -46,6 +46,28 @@ describe('Testing services table', () => { cy.contains(' (1)').should('exist'); cy.contains('3.57%').should('exist'); }); + + it('Verify columns in Services table', () => { + cy.get('.euiFlexItem.euiFlexItem--flexGrow10 .panel-title').contains('Services').should('exist'); + cy.get('.euiTableCellContent__text[title="Name"]').should('exist'); + cy.get('.euiTableCellContent__text[title="Average latency (ms)"]').should('exist'); + cy.get('.euiTableCellContent__text[title="Error rate"]').should('exist'); + cy.get('.euiTableCellContent__text[title="Throughput"]').should('exist'); + cy.get('.euiTableCellContent__text[title="No. of connected services"]').should('exist'); + cy.get('.euiTableCellContent__text[title="Connected services"]').should('exist'); + cy.get('.euiTableCellContent__text[title="Traces"]').should('exist'); + cy.get('[data-test-subj="tablePaginationPopoverButton"]').click(); + cy.get('.euiIcon.euiIcon--medium.euiIcon--inherit.euiContextMenu__icon').eq(0).should('exist').click(); + cy.get('[data-test-subj="pagination-button-next"]').should('exist').click(); + cy.get('.euiLink.euiLink--primary').contains('order').should('exist'); + }) + + it('Navigate from Services to Traces', () => { + cy.get('.euiTableCellContent__text[title="Traces"]').should('exist'); + cy.contains('74').should('exist').click(); + cy.get('.euiText.euiText--medium .panel-title').should('exist'); + cy.get('.euiBadge__childButton[data-test-subj="filterBadge"]').should('exist'); + }) }); describe('Testing service view empty state', () => { @@ -115,9 +137,143 @@ describe('Testing service view', () => { cy.get('.euiTextColor').contains('Span ID').trigger('mouseover'); cy.get('.euiButtonIcon[aria-label="span-flyout-filter-icon"').click({ force: true }); cy.wait(delay); - cy.get('.euiBadge__text').contains('spanId: ').should('exist'); cy.get('[data-test-subj="euiFlyoutCloseButton"]').click({ force: true }); cy.contains('Spans (1)').should('exist'); }); }); + +describe('Testing Service map', () => { + beforeEach(() => { + cy.visit('app/observability-dashboards#/trace_analytics/services', { + onBeforeLoad: (win) => { + win.sessionStorage.clear(); + }, + }); + setTimeFilter(); + }); + + it('Render Service map', () => { + cy.get('.euiText.euiText--medium .panel-title').contains('Service map'); + cy.get('[data-test-subj="latency"]').should('exist'); + cy.get('.ytitle').contains('Latency (ms)'); + cy.get('[data-text = "Error rate"]').click(); + cy.contains('60%'); + cy.get('[data-text = "Throughput"]').click(); + cy.contains('100'); + cy.get('.euiText.euiText--medium').contains('Focus on').should('exist'); + cy.get('[placeholder="Service name"]').focus().type('database{enter}'); + }) +}); + +describe('Testing traces Spans table verify table headers functionality', () => { + beforeEach(() => { + cy.visit('app/observability-dashboards#/trace_analytics/services', { + onBeforeLoad: (win) => { + win.sessionStorage.clear(); + }, + }); + setTimeFilter(); + }); + + it('Renders the spans table and verify columns headers', () => { + cy.contains(' (8)').should('exist'); + cy.contains('analytics-service, frontend-client, recommendation').should('exist'); + cy.get('.euiLink.euiLink--primary').contains('authentication').should('exist').click(); + cy.get('.panel-title').contains('Spans').should('exist'); + cy.get('.panel-title-count').contains('5').should('exist'); + verify_traces_spans_data_grid_cols_exists(); + }); + + it('Toggle columns and verify the columns hidden text verify rows', () => { + cy.get('.euiLink.euiLink--primary').contains('authentication').should('exist').click(); + cy.get('[data-test-subj = "dataGridColumnSelectorButton"]').click(); + cy.get('.euiSwitch.euiSwitch--compressed.euiSwitch--mini .euiSwitch__button').eq(3).click(); + cy.get('.euiButtonEmpty__text').eq(3).click().should('have.text', '2 columns hidden'); + count_table_row(5); + }); + + it('Show all button Spans table', () => { + cy.get('.euiLink.euiLink--primary').contains('authentication').should('exist').click(); + cy.get('[data-test-subj = "dataGridColumnSelectorButton"]').click(); + cy.get('.euiPopoverFooter .euiFlexItem.euiFlexItem--flexGrowZero').eq(0).should('have.text', 'Show all').click(); + cy.get('.euiDataGrid__focusWrap').click().should('exist'); + verify_traces_spans_data_grid_cols_exists(); + }); + + it('Hide all button Spans table', () => { + cy.get('.euiLink.euiLink--primary').contains('authentication').should('exist').click(); + cy.get('[data-test-subj = "dataGridColumnSelectorButton"]').click(); + cy.get('.euiPopoverFooter .euiFlexItem.euiFlexItem--flexGrowZero').eq(1).should('have.text', 'Hide all').click(); + cy.get('.euiDataGrid__focusWrap').click().should('exist'); + cy.get('[data-test-subj="dataGridColumnSelectorPopover"]').should('have.text', '10 columns hidden'); + }); + + it('Render Spans table and change data table Density', () => { + cy.get('.euiLink.euiLink--primary').contains('authentication').should('exist').click(); + verify_traces_spans_data_grid_cols_exists(); + cy.get('.euiButtonEmpty__text').contains('Density').click(); + cy.get('.euiButtonContent__icon').eq(5).click(); + cy.get('.euiButtonContent__icon').eq(6).click(); + cy.get('.euiButtonContent__icon').eq(7).click(); + }); + + it('Render Spans table and and click on sort', () => { + cy.get('.euiLink.euiLink--primary').contains('authentication').should('exist').click(); + verify_traces_spans_data_grid_cols_exists(); + cy.get('[data-test-subj="dataGridColumnSortingButton"]').contains('Sort fields').should('exist').click(); + cy.get('[data-test-subj="dataGridColumnSortingPopoverColumnSelection"]').click(); + cy.get('[data-test-subj="dataGridColumnSortingPopoverColumnSelection-spanId').click(); + cy.get('[data-test-subj="dataGridColumnSortingPopoverColumnSelection-parentSpanId"]').click(); + cy.get('[data-test-subj="dataGridColumnSortingPopoverColumnSelection-traceId"]').click(); + cy.get('[data-test-subj="dataGridColumnSortingPopoverColumnSelection-traceGroup').click(); + cy.get('[data-test-subj="dataGridColumnSortingPopoverColumnSelection-durationInNanos"]').click(); + cy.get('[data-test-subj="dataGridColumnSortingPopoverColumnSelection-startTime"]').click(); + cy.get('[data-test-subj="dataGridColumnSortingPopoverColumnSelection-endTime').click(); + cy.get('[data-test-subj="dataGridColumnSortingPopoverColumnSelection-status.code"]').click(); + cy.get('.euiButtonEmpty__text').eq(5).contains('8 fields sorted').should('exist'); + cy.get('[data-test-subj="dataGridColumnSortingPopoverColumnSelection"]').click(); + cy.get('[data-test-subj="dataGridColumnSortingButton"]').should('exist').click(); + }); +}); + + +describe('Testing traces Spans table and verify columns functionality', () => { + beforeEach(() => { + cy.visit('app/observability-dashboards#/trace_analytics/services', { + onBeforeLoad: (win) => { + win.sessionStorage.clear(); + }, + }); + setTimeFilter(); + }); + + it('Renders the spans table and click on first span to verify details', () => { + cy.get('.euiLink.euiLink--primary').contains('authentication').should('exist').click(); + verify_traces_spans_data_grid_cols_exists(); + cy.get('.euiLink--primary').eq(4).click(); + cy.get('[data-test-subj="spanDetailFlyout"] .euiTitle.euiTitle--medium').contains('Span detail').should('exist'); + cy.get('.euiFlyoutBody .panel-title').contains('Overview').should('exist'); + cy.get('.euiTextColor.euiTextColor--subdued').contains('Span ID').should('exist'); + cy.get('.euiDescriptionList__description .euiFlexItem').eq(0).contains('d03fecfa0f55b77c').should('exist'); + cy.get('.euiFlyoutBody__overflowContent .panel-title').contains('Span attributes').should('exist'); + cy.get('.euiDescriptionList__description .euiFlexItem').eq(0).trigger('mouseover').click(); + cy.get('[aria-label="span-flyout-filter-icon"]').click(); + cy.get('.euiFlyout__closeButton.euiFlyout__closeButton--inside').click(); + cy.get('.euiBadge__content .euiBadge__text').contains('spanId: d03fecfa0f55b77c').should('exist'); + count_table_row(1); + cy.get('[aria-label="remove current filter"]').click(); + count_table_row(5); + }); + + it('Render Spans table and verify Column functionality', () => { + cy.get('.euiLink.euiLink--primary').contains('authentication').should('exist').click(); + verify_traces_spans_data_grid_cols_exists(); + cy.get('.euiDataGridHeaderCell__content').contains('Span ID').click(); + cy.get('.euiListGroupItem__label').contains('Hide column').click(); + cy.get('.euiDataGridHeaderCell__content').contains('Trace ID').click(); + cy.get('.euiListGroupItem__label').contains('Sort A-Z').click(); + cy.get('.euiDataGridHeaderCell__content').contains('Trace group').click(); + cy.get('.euiListGroupItem__label').contains('Move left').click(); + }); +}); diff --git a/dashboards-observability/.cypress/integration/6_trace_analytics_traces.spec.js b/dashboards-observability/.cypress/integration/6_trace_analytics_traces.spec.js index d8c5735fc..14f71ec10 100644 --- a/dashboards-observability/.cypress/integration/6_trace_analytics_traces.spec.js +++ b/dashboards-observability/.cypress/integration/6_trace_analytics_traces.spec.js @@ -113,3 +113,43 @@ describe('Testing trace view', () => { cy.contains('Spans (1)').should('exist'); }); }); + +describe('Testing traces table', () => { + beforeEach(() => { + cy.visit('app/observability-dashboards#/trace_analytics/traces', { + onBeforeLoad: (win) => { + win.sessionStorage.clear(); + }, + }); + setTimeFilter(); + }); + + it('Renders the traces table and verify Table Column, Pagination and Rows Data ', () => { + cy.get('.euiTableCellContent__text').contains('Trace ID').should('exist'); + cy.get('.euiTableCellContent__text').contains('Trace group').should('exist'); + cy.get('.euiTableCellContent__text').contains('Latency (ms)').should('exist'); + cy.get('.euiTableCellContent__text').contains('Percentile in trace group').should('exist'); + cy.get('.euiTableCellContent__text').contains('Errors').should('exist'); + cy.get('.euiTableCellContent__text').contains('Last updated').should('exist'); + cy.get('[data-test-subj="pagination-button-next"]').click(); + cy.contains('client_pay_order').should('exist'); + cy.get('[data-test-subj="pagination-button-previous"]').click(); + cy.contains('224.99').should('exist'); + cy.get('.euiButtonEmpty').contains('5').click(); + cy.contains('690d3c7af1a78cf89c43e...').should('exist'); + cy.contains('5be8370207cbb002a165d...').click(); + cy.contains('client_create_order').should('exist'); + cy.get('path[style*="rgb(116, 146, 231)"]').should('exist'); + cy.go('back'); + cy.wait(delay); + cy.get('.euiButtonEmpty__text').contains('Rows per page').click(); + cy.get('.euiContextMenuItem__text').contains('15 rows').click(); + let expected_row_count=15; + cy.get('.euiTable--auto') + .find("tr") + .then((row) => { + let total=row.length-1; + expect(total).to.equal(expected_row_count); + }); + }); +}); diff --git a/dashboards-observability/.cypress/integration/7_app_analytics.spec.js b/dashboards-observability/.cypress/integration/7_app_analytics.spec.js index 62db0adbe..377b2d323 100644 --- a/dashboards-observability/.cypress/integration/7_app_analytics.spec.js +++ b/dashboards-observability/.cypress/integration/7_app_analytics.spec.js @@ -251,7 +251,7 @@ describe('Viewing application', () => { it('Adds filter when Trace group name is clicked', () => { cy.get('[data-test-subj="app-analytics-overviewTab"]').click(); cy.get('[data-test-subj="dashboard-table-trace-group-name-button"]').contains('client_create_order').click(); - cy.get('.euiTableRow').should('have.length', 1); + cy.get('.euiTableRow').should('have.length', 1, { timeout: timeoutDelay }); cy.get('[data-test-subj="client_create_orderFilterBadge"]').should('exist'); cy.get('[data-test-subj="filterBadge"]').click(); cy.get('[data-test-subj="deleteFilterIcon"]').click(); @@ -560,6 +560,7 @@ describe('Application Analytics home page', () => { cy.get('.euiTableRow').first().within(($row) => { cy.get('.euiCheckbox').click(); }); + cy.wait(delay); cy.get('[data-test-subj="appAnalyticsActionsButton"]').click(); cy.get('[data-test-subj="renameApplicationContextMenuItem"]').click(); cy.get('[data-test-subj="customModalFieldText"]').clear().focus().type(newName); @@ -586,7 +587,8 @@ describe('Application Analytics home page', () => { }); cy.get('[data-test-subj="appAnalyticsActionsButton"]').click(); cy.get('[data-test-subj="deleteApplicationContextMenuItem"]').click(); - cy.get('[data-test-subj="confirmModalConfirmButton"]').click(); + cy.get('[data-test-subj="popoverModal__deleteTextInput"]').type('delete'); + cy.get('[data-test-subj="popoverModal__deleteButton"').click(); cy.wait(delay); cy.get('.euiToast').contains(`Applications successfully deleted!`); cy.get(`[data-test-subj="${newName}ApplicationLink"]`).should('not.exist'); diff --git a/dashboards-observability/.cypress/integration/VisualizationCharts/10_scatter_chart.spec.js b/dashboards-observability/.cypress/integration/VisualizationCharts/10_scatter_chart.spec.js new file mode 100644 index 000000000..d84e23b00 --- /dev/null +++ b/dashboards-observability/.cypress/integration/VisualizationCharts/10_scatter_chart.spec.js @@ -0,0 +1,228 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +/// +import { + delay, + TEST_QUERIES, + querySearch, + landOnEventVisualizations + } from '../../utils/event_constants'; + + const numberOfWindow = 4; + const legendSize = 20; + const pointSize = 30; + const pointSizeUpdated = 35; + const lineWidth = 7; + const lineWidthUpdated = 9; + const fillOpacity = 10; + const fillOpacityUpdated = 50; + const rotateLevel = 45; + const thresholdValue = 50; + + const renderScatterChart = () => { + landOnEventVisualizations(); + querySearch(TEST_QUERIES[6].query, TEST_QUERIES[6].dateRangeDOM); + cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]').type('scatter').type('{enter}'); + }; + + describe('Render scatter chart and verify default behaviour ', () => { + beforeEach(() => { + renderScatterChart(); + }); + + it('Render scatter chart and verify by default the data gets render', () => { + cy.get('.xy').should('exist'); + }); + + it('Render scatter chart and verify you see data configuration panel and chart panel', () => { + cy.get('.euiPanel.euiPanel--paddingSmall').should('have.length', numberOfWindow); + cy.get('.euiTitle.euiTitle--xxsmall').contains('Data Configurations').should('exist'); + cy.get('.euiTitle.euiTitle--xxsmall').contains('Dimensions').should('exist'); + cy.get('.euiTitle.euiTitle--xxsmall').contains('Metrics').should('exist'); + cy.get('.euiIEFlexWrapFix').contains('Panel options').click(); + cy.get('.euiIEFlexWrapFix').contains('Legend').click(); + cy.get('.euiIEFlexWrapFix').contains('Chart styles').click(); + cy.get('.euiIEFlexWrapFix').contains('Color theme').click(); + cy.get('.euiIEFlexWrapFix').contains('Thresholds').click(); + cy.get('[aria-label="Press to toggle this panel"]').eq(1).click(); + cy.get('[aria-label="Press to toggle this panel"]').eq(2).click(); + }); + + it('Render scatter chart and verify the data configuration panel and chart panel are collapsable', () => { + cy.get('.euiPanel.euiPanel--paddingSmall').should('have.length', numberOfWindow); + cy.get('[aria-label="Press to toggle this panel"]').eq(1).click(); + cy.get('[aria-label="Press to toggle this panel"]').eq(2).click(); + }); + }); + + describe('Render scatter chart for data configuration panel', () => { + beforeEach(() => { + renderScatterChart(); + }); + + it('Render scatter chart and verify data config panel', () => { + cy.get('.euiComboBoxPill.euiComboBoxPill--plainText').eq(0).should('contain', 'span(timestamp,1d)'); + cy.get('.euiComboBoxPill.euiComboBoxPill--plainText').eq(1).should('contain', 'count()'); + }); + + it('Render scatter chart and verify data config panel no result found if metric is missing', () => { + cy.get('[data-test-subj="comboBoxClearButton"]').eq(1).click(); + cy.get('.euiTextColor.euiTextColor--subdued').contains('No results found').should('exist'); + cy.get('.euiComboBoxOption__content').contains('count()').click(); + cy.get('.main-svg').contains('No results found').should('not.exist'); + }); + }); + + describe('Render scatter chart for panel options', () => { + beforeEach(() => { + renderScatterChart(); + }); + + it('Render scatter chart and verify the title gets updated according to user input ', () => { + cy.get('input[name="title"]').type("scatter Chart"); + cy.get('textarea[name="description"]').should('exist').click(); + cy.get('.gtitle').contains('scatter Chart').should('exist'); + }); + }); + + describe('Render scatter chart for legend', () => { + beforeEach(() => { + renderScatterChart(); + }); + + it('Render scatter chart and verify legends for Show and Hidden', () => { + cy.get('[data-text="Show"]').should('have.text', 'Show'); + cy.get('[data-text="Show"] [data-test-subj="show"]').should('have.attr', 'checked'); + cy.get('[data-text="Hidden"]').should('have.text', 'Hidden').click(); + cy.get('[data-text="Hidden"] [data-test-subj="hidden"]').should('not.have.attr', 'checked'); + cy.get('[data-unformatted="max(bytes)"]').should('not.exist'); + }); + + it('Render scatter chart and verify legends for position Right and Bottom', () => { + cy.get('[data-text="Right"] [data-test-subj="v"]').should('have.attr', 'checked'); + cy.get('[data-text="Bottom"]').should('have.text', 'Bottom').click(); + cy.get('[data-text="Bottom"] [data-test-subj="h"]').should('not.have.attr', 'checked'); + }); + + it('Render scatter chart and increase Legend Size', () => { + cy.get('[data-test-subj="valueFieldNumber"]').eq(0).click().type(legendSize); + cy.get('textarea[name="description"]').should('exist').click(); + cy.get('.legendtext').should('have.css', 'font-size', '20px'); + }); + }); + + describe('Render scatter chart for Chart Styles ', () => { + beforeEach(() => { + renderScatterChart(); + }); + + it('Render ltime serires and verify chart style of Marker Mode', () => { + cy.get('#configPanel__panelOptions .euiFieldText').click().type('scatter chart'); + cy.get('.euiFlexItem .euiFormRow [placeholder="Description"]').click().type('This is the description for scatter chart with chart style of Points'); + cy.get('[data-text="Marker"]').should('have.text', 'Marker').click(); + cy.get('[data-text="Marker"] [data-test-subj="markers"]').should('have.attr', 'checked'); + + }); + + it('Render scatter chart and verify chart style of Marker Mode with larger Point size', () => { + cy.get('#configPanel__panelOptions .euiFieldText').click().type('scatter chart'); + cy.get('.euiFlexItem .euiFormRow [placeholder="Description"]').click().type('This is the description for scatter chart with chart style of Points'); + cy.get('[data-text="Marker"]').should('have.text', 'Marker').click(); + cy.get('[data-text="Marker"] [data-test-subj="markers"]').should('have.attr', 'checked'); + cy.get('input[type="range"]') + .then($el => $el[0].stepUp(pointSize)) + .trigger('change') + cy.get('.euiRangeSlider').should('have.value', pointSizeUpdated) + + }); + + it('Render scatter chart and verify chart style of Lines+Marker Mode', () => { + cy.get('#configPanel__panelOptions .euiFieldText').click().type('scatter chart'); + cy.get('.euiFlexItem .euiFormRow [placeholder="Description"]').click().type('This is the description for scatter chart with chart style of Lines and Marker'); + cy.get('[data-text="Lines + Markers"]').should('have.text', 'Lines + Markers').click(); + cy.get('[data-text="Lines + Markers"] [data-test-subj="lines+markers"]').should('not.have.attr', 'checked'); + + }); + + it('Render scatter chart and verify chart style of Lines+Marker Mode with Line Width, Fill Opacity and Point Size', () => { + cy.get('#configPanel__panelOptions .euiFieldText').click().type('scatter chart'); + cy.get('.euiFlexItem .euiFormRow [placeholder="Description"]').click().type('This is the description for scatter chart with chart style of Lines and Marker'); + cy.get('[data-text="Lines + Markers"]').should('have.text', 'Lines + Markers').click(); + cy.get('[data-text="Lines + Markers"] [data-test-subj="lines+markers"]').should('not.have.attr', 'checked'); + cy.get('input[type="range"]').eq(0) + .then($el => $el[0].stepUp(lineWidth)) + .trigger('change') + cy.get('.euiRangeSlider').eq(0).should('have.value', lineWidthUpdated) + cy.get('input[type="range"]').eq(1) + .then($el => $el[0].stepUp(fillOpacity)) + .trigger('change') + cy.get('.euiRangeSlider').eq(1).should('have.value', fillOpacityUpdated) + cy.get('input[type="range"]').eq(2) + .then($el => $el[0].stepUp(pointSize)) + .trigger('change') + cy.get('.euiRangeSlider').eq(2).should('have.value', pointSizeUpdated) + cy.get('input[type="range"]').eq(3) + .then($el => $el[0].stepUp(rotateLevel)) + .trigger('change') + cy.get('.euiRangeSlider').eq(3).should('have.value', rotateLevel) + }); + }); + + describe('Render scatter chart for color theme', () => { + beforeEach(() => { + renderScatterChart(); + }); + + it('Render scatter chart and "Add Color theme"', () => { + cy.get('.euiButton__text').contains('+ Add color theme').click(); + cy.wait(delay); + cy.get('[data-test-subj="comboBoxInput"]').eq(5).click(); + cy.get('.euiComboBoxOption__content').contains('count()').click(); + cy.get('path[style*="rgb(252, 5, 5)"]').should('exist'); + + }); + }); + + describe('Render scatter chart and work with Thresholds', () => { + beforeEach(() => { + renderScatterChart(); + }); + + it('Render scatter chart and add threshold', () => { + cy.get('.euiButton__text').contains('+ Add threshold').click(); + cy.get('[data-test-subj="nameFieldText"]').type('scatter chart Threshold'); + cy.get('[data-test-subj="valueFieldNumber"]').eq(1).type(thresholdValue); + cy.get('[data-unformatted="scatter chart Threshold"]').should('be.visible'); + cy.get('path[style*="rgb(252, 5, 5)"]').should('exist'); + }); + }); + + describe('Render scatter chart and verify if reset works properly', () => { + beforeEach(() => { + renderScatterChart(); + }); + + it('Render scatter chart with all feild data then click on reset and verify reset works properly', () => { + cy.get('input[placeholder="Title"]').type('scatter chart'); + cy.get('textarea[placeholder="Description"]').type('Description For scatter chart'); + cy.get('[data-text="Hidden"]').should('have.text', 'Hidden').click(); + cy.get('[data-test-subj="valueFieldNumber"]').eq(0).click().type(legendSize); + cy.get('.euiButton__text').contains('+ Add color theme').click(); + cy.wait(delay); + cy.get('[data-test-subj="comboBoxInput"]').eq(5).click(); + cy.get('.euiComboBoxOption__content').contains('count()').click(); + cy.get('.euiButton__text').contains('+ Add threshold').click(); + cy.get('[data-test-subj="nameFieldText"]').type('scatter chart Threshold'); + cy.get('[data-test-subj="valueFieldNumber"]').eq(1).type(thresholdValue); + cy.get('.euiButtonEmpty__text').contains('Reset').click(); + cy.get('input[placeholder="Title"]').should('not.have.value', 'scatter chart'); + cy.get('textarea[placeholder="Description"]').should('not.have.value', 'Description For scatter chart') + cy.get('[data-text="Show"] [data-test-subj="show"]').should('have.attr', 'checked'); + cy.get('[data-text="Right"] [data-test-subj="v"]').should('have.attr', 'checked'); + cy.get('[data-test-subj="valueFieldNumber"]').eq(0).should('have.value', ''); + }); + }); + \ No newline at end of file diff --git a/dashboards-observability/.cypress/integration/VisualizationCharts/11_horizontalBar_chart.spec.js b/dashboards-observability/.cypress/integration/VisualizationCharts/11_horizontalBar_chart.spec.js new file mode 100644 index 000000000..a93030962 --- /dev/null +++ b/dashboards-observability/.cypress/integration/VisualizationCharts/11_horizontalBar_chart.spec.js @@ -0,0 +1,244 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +/// +import { + delay, + TEST_QUERIES, + querySearch, + landOnEventVisualizations, + } from '../../utils/event_constants'; + + const numberOfWindow = 4; + const labelSize = 20; + const rotateLevel = 45; + const groupWidth = 10; + const groupWidthUpdated = 0.8; + const barWidth = 10; + const barWidthUpdated = 80; + const lineWidth = 7; + const lineWidthUpdated = 8; + const fillOpacity = 10; + const fillOpacityUpdated = 90; + const numberOfColor = 24; + + const renderHorizontalBarChart = () => { + landOnEventVisualizations(); + querySearch(TEST_QUERIES[4].query, TEST_QUERIES[4].dateRangeDOM); + cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]') + .type('Horizontal Bar') + .type('{enter}'); + }; + + describe('Render horizontal bar chart and verify default behaviour ', () => { + beforeEach(() => { + renderHorizontalBarChart(); + }); + + it('Render horizontal bar chart and verify by default the data gets render', () => { + cy.get('.xy').should('exist'); + }); + + it('Render horizontal bar chart and verify you see data configuration panel and chart panel', () => { + cy.get('.euiPanel.euiPanel--paddingSmall').should('have.length', numberOfWindow); + cy.get('.euiTitle.euiTitle--xxsmall').contains('Data Configurations').should('exist'); + cy.get('.euiTitle.euiTitle--xxsmall').contains('Dimensions').should('exist'); + cy.get('.euiTitle.euiTitle--xxsmall').contains('Metrics').should('exist'); + cy.get('.euiIEFlexWrapFix').contains('Panel options').click(); + cy.get('.euiIEFlexWrapFix').contains('Legend').click(); + cy.get('.euiIEFlexWrapFix').contains('Chart styles').click(); + cy.get('.euiIEFlexWrapFix').contains('Color theme').click(); + cy.get('[aria-label="Press to toggle this panel"]').eq(1).click(); + cy.get('[aria-label="Press to toggle this panel"]').eq(2).click(); + }); + + it('Render horizontal bar chart and verify the data configuration panel and chart panel are collapsable', () => { + cy.get('.euiPanel.euiPanel--paddingSmall').should('have.length', numberOfWindow); + cy.get('[aria-label="Press to toggle this panel"]').eq(1).click(); + cy.get('[aria-label="Press to toggle this panel"]').eq(2).click(); + }); + }); + + describe('Render horizontal bar chart for data configuration panel', () => { + beforeEach(() => { + renderHorizontalBarChart(); + }); + + it('Render horizontal bar chart and verify data config panel', () => { + cy.get('.euiComboBoxPill.euiComboBoxPill--plainText').eq(0).should('contain', 'tags'); + cy.get('.euiComboBoxPill.euiComboBoxPill--plainText').eq(1).should('contain', 'count()'); + cy.get('.euiComboBoxPill.euiComboBoxPill--plainText').eq(2).should('contain', 'avg(bytes)'); + cy.get('.euiComboBoxPill.euiComboBoxPill--plainText').eq(3).should('contain', 'host'); + }); + + it('Render horizontal bar chart and verify data config panel restrict user to select a duplicate field on dimension field', () => { + cy.get('[data-test-subj="comboBoxInput"]').eq(1).click(); + cy.get('[data-test-subj="comboBoxClearButton"]').eq(0).click(); + cy.get('[data-test-subj="comboBoxInput"]').eq(1).click(); + cy.get('.euiComboBoxOption__content').should('have.length', 1); + cy.get('.euiComboBoxOption__content').contains('tags'); + }); + + it('Render horizontal bar chart and verify data config panel Restrict user to select a duplicate field on Metrics field', () => { + cy.get('.euiText.euiText--extraSmall').eq(1).click(); + cy.get('[data-test-subj="comboBoxClearButton"]').eq(1).click(); + cy.get('[data-test-subj="comboBoxInput"]').eq(3).click(); + cy.get('.euiComboBoxOption__content').should('not.contain', 'tags'); + cy.get('.euiComboBoxOption__content').should('have.length', 2); + }); + + it('Render horizontal bar chart and verify data config panel no result found if metric is missing', () => { + cy.get('.euiText.euiText--extraSmall').eq(0).click(); + cy.get('.euiText.euiText--extraSmall').eq(1).click(); + cy.get('[data-test-subj="comboBoxClearButton"]').eq(1).click(); + cy.get('[data-test-subj="comboBoxInput"]').eq(0).click(); + cy.get('.euiButton__text').contains('Update chart').click(); + cy.get('.euiTextColor.euiTextColor--subdued').contains('No results found').should('exist'); + cy.get('[data-test-subj="comboBoxInput"]').eq(3).click(); + cy.get('.euiComboBoxOption__content').contains('avg(bytes)').click(); + cy.get('.euiButton__text').contains('Update chart').click(); + cy.get('.main-svg').contains('No results found').should('not.exist'); + }); + }); + + describe('Render horizontal bar chart for panel options', () => { + beforeEach(() => { + renderHorizontalBarChart(); + }); + + it('Render horizontal bar chart and verify the title gets updated according to user input ', () => { + cy.get('input[name="title"]').type('horizontal bar chart'); + cy.get('textarea[name="description"]').should('exist').click(); + cy.get('.gtitle').contains('horizontal bar chart').should('exist'); + }); + }); + + describe('Render horizontal bar chart for legend', () => { + beforeEach(() => { + renderHorizontalBarChart(); + }); + + it('Render horizontal bar chart and verify legends for Show and Hidden', () => { + cy.get('[data-text="Show"]').should('have.text', 'Show'); + cy.get('[data-text="Show"] [data-test-subj="show"]').should('have.attr', 'checked'); + cy.get('[data-text="Hidden"]').should('have.text', 'Hidden').click(); + cy.get('[data-text="Hidden"] [data-test-subj="hidden"]').should('not.have.attr', 'checked'); + cy.get('[data-unformatted="max(bytes)"]').should('not.exist'); + }); + + it('Render horizontal bar chart and verify legends for position Right and Bottom', () => { + cy.get('[data-text="Right"]').should('have.text', 'Right'); + cy.get('[data-text="Right"] [data-test-subj="v"]').should('have.attr', 'checked'); + cy.get('[data-text="Bottom"]').should('have.text', 'Bottom').click(); + cy.get('[data-text="Bottom"] [data-test-subj="h"]').should('not.have.attr', 'checked'); + }); + }); + + describe('Render horizontal bar chart for chart style options', () => { + beforeEach(() => { + renderHorizontalBarChart(); + }); + + it('Render horizontal bar chart and increase Label Size ', () => { + cy.get('[data-test-subj="valueFieldNumber"]').click().type(labelSize); + cy.get('textarea[name="description"]').should('exist').click(); + cy.get('[data-unformatted="login"]').should('have.css', 'font-size', '20px'); + }); + + it('Render horizontal bar chart and "Rotate bar labels"', () => { + cy.get('input[type="range"]') + .eq(0) + .then(($el) => $el[0].stepUp(rotateLevel)) + .trigger('change'); + cy.get('.euiRangeSlider').eq(0).should('have.value', rotateLevel); + }); + + it('Render horizontal bar chart and change "Group Width"', () => { + cy.get('input[type="range"]') + .eq(1) + .then(($el) => $el[0].stepUp(groupWidth)) + .trigger('change'); + cy.get('.euiRangeSlider').eq(1).should('have.value', groupWidthUpdated); + }); + + it('Render horizontal bar chart and change "Bar Width"', () => { + cy.get('input[type="range"]') + .eq(2) + .then(($el) => $el[0].stepDown(barWidth)) + .trigger('change'); + cy.get('.euiRangeSlider').eq(4).should('have.value', barWidthUpdated); + }); + + it('Render horizontal bar chart and change "Line Width"', () => { + cy.get('input[type="range"]') + .eq(3) + .then(($el) => $el[0].stepUp(lineWidth)) + .trigger('change'); + cy.get('.euiRangeSlider').eq(3).should('have.value', lineWidthUpdated); + }); + + it('Render horizontal bar chart and change "Fill Opacity"', () => { + cy.get('input[type="range"]') + .eq(4) + .then(($el) => $el[0].stepUp(fillOpacity)) + .trigger('change'); + cy.get('.euiRangeSlider').eq(4).should('have.value', fillOpacityUpdated); + }); + }); + + describe('Render horizontal bar chart for color theme', () => { + beforeEach(() => { + renderHorizontalBarChart(); + }); + + it('Render horizontal bar chart and "Add color theme"', () => { + cy.get('.euiButton__text').contains('+ Add color theme').click(); + cy.wait(delay); + cy.get('[data-test-subj="comboBoxInput"]').eq(9).click(); + cy.get('.euiComboBoxOption__content').contains('avg(bytes)').click(); + cy.get('.point').find('path[style*="rgb(252, 5, 5)"]').should('have.length', numberOfColor); + }); + }); + + describe('Render horizontal bar chart and verify if reset works properly', () => { + beforeEach(() => { + renderHorizontalBarChart(); + }); + + it('Render horizontal bar chart with all feild data then click on reset and verify reset works properly', () => { + cy.get('input[placeholder="Title"]').type('horizontal bar chart'); + cy.get('textarea[placeholder="Description"]').type('Description For horizontal bar chart'); + cy.get('.euiButton__text').contains('Hidden').click(); + cy.get('.euiButton__text').contains('Stack').click(); + cy.get('[data-test-subj="valueFieldNumber"]').click().type(labelSize); + cy.get('input[type="range"]') + .eq(0) + .then(($el) => $el[0].stepUp(rotateLevel)) + .trigger('change'); + cy.get('input[type="range"]') + .eq(1) + .then(($el) => $el[0].stepUp(groupWidth)) + .trigger('change'); + cy.get('input[type="range"]') + .eq(2) + .then(($el) => $el[0].stepDown(barWidth)) + .trigger('change'); + cy.get('input[type="range"]') + .eq(3) + .then(($el) => $el[0].stepUp(lineWidth)) + .trigger('change'); + cy.get('.euiButtonEmpty__text').contains('Reset').click(); + cy.get('input[placeholder="Title"]').should('not.have.value', 'horizontal bar chart'); + cy.get('textarea[placeholder="Description"]').should( + 'not.have.value', + 'Description For horizontal bar chart' + ); + cy.get('[data-text="Show"] [data-test-subj="show"]').should('have.attr', 'checked'); + cy.get('[data-text="Right"] [data-test-subj="v"]').should('have.attr', 'checked'); + cy.get('[data-text="Vertical"] [data-test-subj="v"]').should('have.attr', 'checked'); + cy.get('[data-text="Group"] [data-test-subj="group"]').should('have.attr', 'checked'); + cy.get('[data-test-subj="valueFieldNumber"]').should('have.value', ''); + }); + }); diff --git a/dashboards-observability/.cypress/integration/VisualizationCharts/12_boxPlot_chart.spec.js b/dashboards-observability/.cypress/integration/VisualizationCharts/12_boxPlot_chart.spec.js new file mode 100644 index 000000000..d4dae465e --- /dev/null +++ b/dashboards-observability/.cypress/integration/VisualizationCharts/12_boxPlot_chart.spec.js @@ -0,0 +1,248 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +/// +import { + delay, + TEST_QUERIES, + querySearch, + landOnEventVisualizations, +} from '../../utils/event_constants'; + +const numberOfWindow = 4; +const labelSize = 20; +const rotateLevel = 45; +const boxSize = 7; +const boxSizeUpdated = 1; +const markerSize = 5; +const markerSizeUpdated = 1; +const jitter = 2; +const jitterUpdated = .1; +const fillOpacity = 10; +const fillOpacityUpdated = 50; +const numberOfColor = 24; + +const renderBoxPlot = () => { + landOnEventVisualizations(); + querySearch(TEST_QUERIES[4].query, TEST_QUERIES[4].dateRangeDOM); + cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]') + .type('Box plot') + .type('{enter}'); +}; + +describe('Render box plot and verify default behaviour ', () => { + beforeEach(() => { + renderBoxPlot(); + }); + + it('Render box plot and verify by default the data gets render', () => { + cy.get('.xy').should('exist'); + }); + + it('Render box plot and verify you see data configuration panel and chart panel', () => { + cy.get('.euiPanel.euiPanel--paddingSmall').should('have.length', numberOfWindow); + cy.get('.euiTitle.euiTitle--xxsmall').contains('Data Configurations').should('exist'); + cy.get('.euiTitle.euiTitle--xxsmall').contains('Dimensions').should('exist'); + cy.get('.euiTitle.euiTitle--xxsmall').contains('Metrics').should('exist'); + cy.get('.euiIEFlexWrapFix').contains('Panel options').click(); + cy.get('.euiIEFlexWrapFix').contains('Legend').click(); + cy.get('.euiIEFlexWrapFix').contains('Chart styles').click(); + cy.get('.euiIEFlexWrapFix').contains('Color Theme').click(); + cy.get('[aria-label="Press to toggle this panel"]').eq(1).click(); + cy.get('[aria-label="Press to toggle this panel"]').eq(2).click(); + }); + + it('Render box plot and verify the data configuration panel and chart panel are collapsable', () => { + cy.get('.euiPanel.euiPanel--paddingSmall').should('have.length', numberOfWindow); + cy.get('[aria-label="Press to toggle this panel"]').eq(1).click(); + cy.get('[aria-label="Press to toggle this panel"]').eq(2).click(); + }); +}); + +describe('Render box plot for data configuration panel', () => { + beforeEach(() => { + renderBoxPlot(); + }); + + it('Render box plot and verify data config panel', () => { + cy.get('.euiComboBoxPill.euiComboBoxPill--plainText').eq(0).should('contain', 'tags'); + cy.get('.euiComboBoxPill.euiComboBoxPill--plainText').eq(1).should('contain', 'count()'); + cy.get('.euiComboBoxPill.euiComboBoxPill--plainText').eq(2).should('contain', 'avg(bytes)'); + cy.get('.euiComboBoxPill.euiComboBoxPill--plainText').eq(3).should('contain', 'host'); + }); + + it('Render box plot and verify data config panel restrict user to select a duplicate field on dimension field', () => { + cy.get('[data-test-subj="comboBoxInput"]').eq(1).click(); + cy.get('[data-test-subj="comboBoxClearButton"]').eq(0).click(); + cy.get('[data-test-subj="comboBoxInput"]').eq(1).click(); + cy.get('.euiComboBoxOption__content').should('have.length', 1); + cy.get('.euiComboBoxOption__content').contains('tags'); + }); + + it('Render box plot and verify data config panel Restrict user to select a duplicate field on Metrics field', () => { + cy.get('.euiText.euiText--extraSmall').eq(1).click(); + cy.get('[data-test-subj="comboBoxClearButton"]').eq(1).click(); + cy.get('[data-test-subj="comboBoxInput"]').eq(3).click(); + cy.get('.euiComboBoxOption__content').should('not.contain', 'tags'); + cy.get('.euiComboBoxOption__content').should('have.length', 2); + }); + + it('Render box plot and verify data config panel no result found if metric is missing', () => { + cy.get('.euiText.euiText--extraSmall').eq(0).click(); + cy.get('.euiText.euiText--extraSmall').eq(1).click(); + cy.get('[data-test-subj="comboBoxClearButton"]').eq(1).click(); + cy.get('[data-test-subj="comboBoxInput"]').eq(0).click(); + cy.get('.euiButton__text').contains('Update chart').click(); + cy.get('.euiTextColor.euiTextColor--subdued').contains('No results found').should('exist'); + cy.get('[data-test-subj="comboBoxInput"]').eq(3).click(); + cy.get('.euiComboBoxOption__content').contains('avg(bytes)').click(); + cy.get('.euiButton__text').contains('Update chart').click(); + cy.get('.main-svg').contains('No results found').should('not.exist'); + }); +}); + +describe('Render box plot for panel options', () => { + beforeEach(() => { + renderBoxPlot(); + }); + + it('Render box plot and verify the title gets updated according to user input ', () => { + cy.get('input[name="title"]').type('box plot'); + cy.get('textarea[name="description"]').should('exist').click(); + cy.get('.gtitle').contains('box plot').should('exist'); + }); +}); + +describe('Render box plot for legend', () => { + beforeEach(() => { + renderBoxPlot(); + }); + + it('Render box plot and verify legends for Show and Hidden', () => { + cy.get('[data-text="Show"]').should('have.text', 'Show'); + cy.get('[data-text="Show"] [data-test-subj="show"]').should('have.attr', 'checked'); + cy.get('[data-text="Hidden"]').should('have.text', 'Hidden').click(); + cy.get('[data-text="Hidden"] [data-test-subj="hidden"]').should('not.have.attr', 'checked'); + cy.get('[data-unformatted="max(bytes)"]').should('not.exist'); + }); + + it('Render box plot and verify legends for position Right and Bottom', () => { + cy.get('[data-text="Right"]').should('have.text', 'Right'); + cy.get('[data-text="Right"] [data-test-subj="v"]').should('have.attr', 'checked'); + cy.get('[data-text="Bottom"]').should('have.text', 'Bottom').click(); + cy.get('[data-text="Bottom"] [data-test-subj="h"]').should('not.have.attr', 'checked'); + }); +}); + +describe('Render box plot for chart style options', () => { + beforeEach(() => { + renderBoxPlot(); + }); + + it('Render box plot and increase Label Size ', () => { + cy.get('[data-test-subj="valueFieldNumber"]').click().type(labelSize); + cy.get('textarea[name="description"]').should('exist').click(); + cy.get('[data-unformatted="count()"]').should('have.css', 'font-size', '20px'); + }); + + it('Render box plot and "Rotate box labels"', () => { + cy.get('input[type="range"]') + .eq(0) + .then(($el) => $el[0].stepUp(rotateLevel)) + .trigger('change'); + cy.get('.euiRangeSlider').eq(0).should('have.value', rotateLevel); + }); + + it('Render box plot and change "Box gap"', () => { + cy.get('input[type="range"]') + .eq(1) + .then(($el) => $el[0].stepUp(boxSize)) + .trigger('change'); + cy.get('.euiRangeSlider').eq(1).should('have.value', boxSizeUpdated); + }); + + it('Render box plot and change "Marker size"', () => { + cy.get('input[type="range"]') + .eq(2) + .then(($el) => $el[0].stepDown(markerSize)) + .trigger('change'); + cy.get('.euiRangeSlider').eq(2).should('have.value', markerSizeUpdated); + }); + + it('Render box plot and change "Jitter"', () => { + cy.get('input[type="range"]') + .eq(3) + .then(($el) => $el[0].stepDown(jitter)) + .trigger('change'); + cy.get('.euiRangeSlider').eq(3).should('have.value', jitterUpdated); + }); + + it('Render box plot and change "Fill opacity"', () => { + cy.get('input[type="range"]') + .eq(4) + .then(($el) => $el[0].stepUp(fillOpacity)) + .trigger('change'); + cy.get('.euiRangeSlider').eq(4).should('have.value', fillOpacityUpdated); + }); +}); + +describe('Render box plot for color theme', () => { + beforeEach(() => { + renderBoxPlot(); + }); + + it('Render box plot and "Add color theme"', () => { + cy.get('.euiButton__text').contains('+ Add color theme').click(); + cy.wait(delay); + cy.get('[data-test-subj="comboBoxInput"]').eq(9).click(); + cy.get('.euiComboBoxOption__content').contains('avg(bytes)').click(); + cy.get('.points').find('path[style*="rgb(252, 5, 5)"]').should('have.length', numberOfColor); + }); +}); + +describe('Render box plot and verify if reset works properly', () => { + beforeEach(() => { + renderBoxPlot(); + }); + + it('Render box plot with all feild data then click on reset and verify reset works properly', () => { + cy.get('input[placeholder="Title"]').type('box plot'); + cy.get('textarea[placeholder="Description"]').type('Description For box plot'); + cy.get('.euiButton__text').contains('Hidden').click(); + cy.get('.euiButton__text').contains('Horizontal').click(); + cy.get('[data-test-subj="valueFieldNumber"]').click().type(labelSize); + cy.get('input[type="range"]') + .eq(0) + .then(($el) => $el[0].stepUp(rotateLevel)) + .trigger('change'); + cy.get('input[type="range"]') + .eq(1) + .then(($el) => $el[0].stepUp(boxSize)) + .trigger('change'); + cy.get('input[type="range"]') + .eq(2) + .then(($el) => $el[0].stepDown(markerSize)) + .trigger('change'); + cy.get('input[type="range"]') + .eq(3) + .then(($el) => $el[0].stepUp(jitter)) + .trigger('change'); + cy.get('input[type="range"]') + .eq(4) + .then(($el) => $el[0].stepUp(fillOpacity)) + .trigger('change'); + cy.get('.euiButtonEmpty__text').contains('Reset').click(); + cy.get('input[placeholder="Title"]').should('not.have.value', 'box plot'); + cy.get('textarea[placeholder="Description"]').should( + 'not.have.value', + 'Description For box plot' + ); + cy.get('[data-text="Show"] [data-test-subj="show"]').should('have.attr', 'checked'); + cy.get('[data-text="Right"] [data-test-subj="v"]').should('have.attr', 'checked'); + cy.get('[data-text="Vertical"] [data-test-subj="v"]').should('have.attr', 'checked'); + cy.get('[data-text="Overlay"] [data-test-subj="overlay"]').should('have.attr', 'checked'); + cy.get('[data-test-subj="valueFieldNumber"]').should('have.value', ''); + }); +}); diff --git a/dashboards-observability/.cypress/integration/VisualizationCharts/13_logsView.spec.js b/dashboards-observability/.cypress/integration/VisualizationCharts/13_logsView.spec.js new file mode 100644 index 000000000..542e3d776 --- /dev/null +++ b/dashboards-observability/.cypress/integration/VisualizationCharts/13_logsView.spec.js @@ -0,0 +1,241 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +/// +import { + delay, + TEST_QUERIES, + querySearch, + landOnEventVisualizations, + saveVisualizationAndVerify, + deleteVisualization, +} from '../../utils/event_constants'; + +const renderLogsView = () => { + landOnEventVisualizations(); + querySearch(TEST_QUERIES[8].query, TEST_QUERIES[8].dateRangeDOM); + cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]') + .type('Logs view') + .type('{enter}'); +}; + +const renderLogsViewChart = () => { + landOnEventVisualizations(); + querySearch(TEST_QUERIES[2].query, TEST_QUERIES[2].dateRangeDOM); + cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]') + .type('Logs view') + .type('{enter}'); +}; + +const fieldName = 'host'; + +describe('Render Logs view and verify default behavior', () => { + beforeEach(() => { + renderLogsView(); + }); + + it('Render Logs view and verify the default data', () => { + cy.get('.logs-view-container').should('exist'); + }); + + it('Render Logs view and verify Data Configuration panel default behavior', () => { + cy.get('.euiTitle.euiTitle--xxsmall').contains('Data Configurations').should('exist'); + cy.get('.euiTitle.euiTitle--xxsmall').contains('Columns'); + cy.get('.euiFormLabel.euiFormRow__label').contains('Field'); + cy.get('.euiButton.euiButton--primary.euiButton--fullWidth.euiButton-isDisabled').should( + 'be.disabled' + ); + cy.get('[data-test-subj="visualizeEditorRenderButton"]').should('be.disabled'); + }); + + it('Render Logs view and verify Style section for Logs view', () => { + cy.get('.vis-config-tabs .euiTab__content').contains('Style').should('exist'); + cy.get('.euiAccordion__triggerWrapper').contains('Panel options').should('exist'); + cy.get('#configPanel__panelOptions .euiFormRow__labelWrapper') + .contains('Title') + .should('exist'); + cy.get('#configPanel__panelOptions .euiFormRow__labelWrapper') + .contains('Description') + .should('exist'); + }); + + it('Table view should be enabled for Logs view', () => { + cy.get('.euiSwitch__label').contains('Table view').should('exist'); + cy.get('[data-test-subj="workspace__dataTableViewSwitch"][aria-checked="false"]').click(); + cy.get('.ag-header.ag-pivot-off').should('exist'); + }); + + it('Verify Style section for Logs view', () => { + cy.get('#data-panel').contains('Style').should('exist'); + cy.get('.euiAccordion__button').contains('Panel options').should('exist'); + cy.get('#configPanel__panelOptions').contains('Title').should('exist'); + cy.get('.euiFormHelpText.euiFormRow__text').contains('Name your visualization').should('exist'); + cy.get('#configPanel__panelOptions').contains('Description').should('exist'); + }); + + it('Add and Remove toggle buttons for fields section', () => { + cy.get('#available_fields').contains('Available Fields').should('exist'); + cy.get('[aria-label="Add agent to table"]').should('be.disabled'); + cy.get('#selected_fields').contains('Query fields').should('exist'); + cy.get('[aria-label="Remove clientip from table"]').should('be.disabled'); + }); +}); + +describe('Save and Delete Visualization', () => { + beforeEach(() => { + renderLogsView(); + }); + + it('Render Logs view, Save and Delete Visualization', () => { + saveVisualizationAndVerify(); + deleteVisualization(); + }); +}); + +describe('Render Logs view with no stats section in the query', () => { + beforeEach(() => { + renderLogsViewChart(); + }); + + it('Disabled Table view toogle button', () => { + cy.get('[data-test-subj="workspace__dataTableViewSwitch"]').should('be.disabled'); + }); + + it('Save toast message', () => { + const vis_name_sub_string = Math.floor(Math.random() * 100); + cy.get('[data-test-subj="eventExplorer__saveManagementPopover"]').click(); + cy.get('[data-test-subj="eventExplorer__querySaveComboBox"]').click(); + cy.get('.euiComboBoxOptionsList__rowWrap .euiFilterSelectItem').eq(0).click(); + cy.get( + '.euiPopover__panel .euiFormControlLayoutIcons [data-test-subj="comboBoxToggleListButton"]' + ) + .eq(0) + .click(); + cy.get('.euiPopover__panel input') + .eq(1) + .type(`Test visualization` + vis_name_sub_string); + cy.get('[data-test-subj="eventExplorer__querySaveConfirm"]').click(); + cy.get('[data-test-subj="euiToastHeader"]') + .contains('There is no query or(and) visualization to save') + .should('exist'); + }); + + it('Verify Logs view details when PPL query does not have stats section ', () => { + cy.get('[data-test-subj="docTable"]').should('exist'); + cy.get('.osdDocTableHeader').contains('Time').should('exist'); + cy.get('.osdDocTableHeader').contains('_source').should('exist'); + }); + + it('Add and Remove toggle buttons for fields section should be enabled', () => { + //Add field + cy.get('[data-test-subj="fieldToggle-agent"]').click(); + cy.get('[data-test-subj="field-agent"]').should('exist'); + //Remove field + cy.get('[data-test-subj="fieldToggle-agent"]').click(); + cy.get('[aria-labelledby="selected_fields"] [data-test-subj="field-agent-showDetails"]').should( + 'not.exist' + ); + }); + + it('Search engine for fields under Visualizations', () => { + cy.get('[data-test-subj="eventExplorer__sidebarSearch"]').should('exist').type(fieldName); + cy.get('[data-test-subj="fieldToggle-host"]').click(); + cy.get('[data-test-subj="fieldList-selected"]').should('exist'); + }); + + it('View surrounding events button enabled', () => { + cy.get('.euiIcon.euiIcon--medium.euiIcon--inherit.euiButtonIcon__icon') + .eq(2) + .click({ force: true }); + cy.get('#eventsDocFyout').contains('Event Details').should('exist'); + cy.get('.euiButton__text').eq(4).should('not.be.disabled'); + }); +}); + +describe('Event Details overlay', () => { + beforeEach(() => { + renderLogsView(); + }); + + it('Verify Event Details overaly should get opened after clicking on details toggle button', () => { + cy.get('.euiIcon.euiIcon--medium.euiIcon--inherit.euiButtonIcon__icon') + .eq(2) + .click({ force: true }); + cy.get('#eventsDocFyout').contains('Event Details').should('exist'); + }); + + it('Options in Event Details overlay', () => { + cy.get('.euiIcon.euiIcon--medium.euiIcon--inherit.euiButtonIcon__icon') + .eq(2) + .click({ force: true }); + cy.get('#eventsDocFyout').contains('Event Details').should('exist'); + cy.get('.euiTabs .euiTab__content').contains('Table'); + cy.get('.table.table-condensed.osdDocViewerTable').should('exist'); + cy.get('.euiTabs .euiTab__content').contains('JSON').click(); + cy.get('.euiCodeBlock__code.json').should('exist'); + cy.get('.euiTabs .euiTab__content').contains('Traces').click(); + cy.get('.euiCallOutHeader__title').contains('No Trace Id found in the event.').should('exist'); + cy.get('.euiLink.euiLink--primary').contains('Trace Analytics').click(); + cy.get('#trace-analytics').contains('Trace Analytics').should('exist'); + cy.get('.euiLink.euiLink--primary').contains('Log Correlation').click(); + cy.get('#log-correlation').contains('Log Correlation').should('exist'); + }); + + it('View surrounding events button disabled', () => { + cy.get('.euiIcon.euiIcon--medium.euiIcon--inherit.euiButtonIcon__icon') + .eq(2) + .click({ force: true }); + cy.get('#eventsDocFyout').contains('Event Details').should('exist'); + cy.get('.euiButton.euiButton--primary.euiButton-isDisabled.header-button') + .contains('View surrounding events') + .should('be.disabled'); + }); + + it('Event Details overlay resizable and "X" buttons', () => { + cy.get('.euiIcon.euiIcon--medium.euiIcon--inherit.euiButtonIcon__icon') + .eq(2) + .click({ force: true }); + cy.get('#eventsDocFyout').contains('Event Details').should('exist'); + cy.get('[title="Resize"]').click(); + cy.get('.euiIcon.euiIcon--medium.euiIcon--inherit.euiButtonIcon__icon') + .eq(2) + .click({ force: true }); + cy.get('#eventsDocFyout').contains('Event Details').should('exist'); + cy.get('[data-test-subj="euiFlyoutCloseButton"]').should('exist').click(); + }); + + it('Table details on Event Details overlay', () => { + cy.get('.euiIcon.euiIcon--medium.euiIcon--inherit.euiButtonIcon__icon') + .eq(2) + .click({ force: true }); + cy.get('#eventsDocFyout').contains('Event Details').should('exist'); + cy.get('[data-test-subj="docTable"]').should('exist'); + }); +}); + +describe('Data Configuration panel when no stats in the query', () => { + beforeEach(() => { + renderLogsViewChart(); + }); + + it('Data Configuration panel default behavior', () => { + cy.get('.euiTitle.euiTitle--xxsmall').contains('Data Configurations').should('exist'); + cy.get('.euiTitle.euiTitle--xxsmall').contains('Columns').should('exist'); + cy.get('.euiButton__text').eq(2).contains('Add').should('not.be.disabled'); + cy.get('.euiButton__text').eq(3).contains('Update Chart').should('not.be.disabled'); + }); + + it('Add button in Data Configuration panel', () => { + cy.get('.euiTitle.euiTitle--xxsmall').contains('Data Configurations').should('exist'); + cy.get('.euiTitle.euiTitle--xxsmall').contains('Columns').should('exist'); + cy.get('.euiButton__text').eq(2).contains('Add').should('not.be.disabled').click(); + cy.get('.euiFormLabel.euiFormRow__label').contains('Field'); + cy.get('.euiIcon.euiIcon--medium.euiIcon--danger').should('exist'); + cy.get('[data-test-subj="comboBoxToggleListButton"]').eq(0).click(); + cy.get('.euiFlexItem.euiFilterSelectItem__content').eq(1).click(); + cy.get('.euiButton__text').contains('Update Chart').should('not.be.disabled').click(); + cy.get('[data-test-subj="docTable"]').should('exist'); + }); +}); diff --git a/dashboards-observability/.cypress/integration/VisualizationCharts/9_coordinateMap_chart.spec.js b/dashboards-observability/.cypress/integration/VisualizationCharts/9_coordinateMap_chart.spec.js new file mode 100644 index 000000000..175011188 --- /dev/null +++ b/dashboards-observability/.cypress/integration/VisualizationCharts/9_coordinateMap_chart.spec.js @@ -0,0 +1,195 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +/// +import { + TEST_QUERIES, + querySearch, + landOnEventVisualizations +} from '../../utils/event_constants'; + +const numberOfWindow = 4; +const labelSize = 20; +const latitudeRangeMin = 40; +const latitudeRangeMax = 70; +const longitudeRangeMin = -130; +const longitudeRangeMax = -55; + +const renderCoordinateMap = () => { + landOnEventVisualizations(); + querySearch(TEST_QUERIES[0].query, TEST_QUERIES[0].dateRangeDOM); + cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]').type('Coordinate Map').type('{enter}'); +}; + +const renderDataForCoordinateMap = () => { + cy.get('[data-test-subj="comboBoxInput"]').eq(1).click(); + cy.get('.euiComboBoxOption__content').contains('DestLocation').click(); + cy.get('[data-test-subj="comboBoxInput"]').eq(3).click(); + cy.get('.euiComboBoxOption__content').contains('AvgTicketPrice').click(); + cy.get('[data-test-subj="comboBoxInput"]').eq(4).click(); + cy.get('.euiComboBoxOption__content').contains('Dest').click(); + cy.get('.euiButton__text').contains('Update chart').click(); + cy.get('.layer.land').should('exist'); + cy.get('stop[stop-color="rgb(5, 10, 172)"]').should('exist'); +} + +describe('Render coordinate map and verify default behaviour ', () => { + beforeEach(() => { + renderCoordinateMap(); + }); + + it('Render coordinate map and verify by default the data dont gets render', () => { + cy.get('.layer.land').should('not.exist'); + cy.get('.euiTextColor.euiTextColor--subdued').contains('No results found').should('exist'); + }); + + it('Render coordinate map and verify you see data configuration panel and chart panel', () => { + cy.get('.euiPanel.euiPanel--paddingSmall').should('have.length', numberOfWindow); + cy.get('.euiTitle.euiTitle--xxsmall').contains('Data Configurations').should('exist'); + cy.get('.euiTitle.euiTitle--xxsmall').contains('Dimensions').should('exist'); + cy.get('.euiTitle.euiTitle--xxsmall').contains('Metrics').should('exist'); + cy.get('.euiIEFlexWrapFix').contains('Panel options').click(); + cy.get('.euiIEFlexWrapFix').contains('Text').click(); + cy.get('.euiIEFlexWrapFix').contains('Chart styles').click(); + cy.get('[aria-label="Press to toggle this panel"]').eq(1).click(); + cy.get('[aria-label="Press to toggle this panel"]').eq(2).click(); + }); + + it('Render coordinate map and verify the data configuration panel and chart panel are collapsable', () => { + cy.get('.euiPanel.euiPanel--paddingSmall').should('have.length', numberOfWindow); + cy.get('[aria-label="Press to toggle this panel"]').eq(1).click(); + cy.get('[aria-label="Press to toggle this panel"]').eq(2).click(); + }); +}); + +describe('Render coordinate map for data configuration panel', () => { + beforeEach(() => { + renderCoordinateMap(); + }); + + it('Render coordinate map and verify data config panel', () => { + cy.get('[data-test-subj="comboBoxInput"]').eq(1).contains('Select a field').should('exist'); + cy.get('[data-test-subj="comboBoxInput"]').eq(3).contains('Select a field').should('exist'); + cy.get('[data-test-subj="comboBoxInput"]').eq(4).contains('Select a field').should('exist'); + }); + + it('Render coordinate map and verify data gets render only after selecting the field value in data configuration panel', () => { + renderDataForCoordinateMap(); + }); + + it('Render coordinate map and verify data config dimensions panel "Field" contains only location', () => { + cy.get('[data-test-subj="comboBoxInput"]').eq(1).click(); + cy.get('.euiComboBoxOption__content').contains('DestLocation').should('exist'); + cy.get('.euiComboBoxOption__content').contains('OriginLocation').should('exist'); + }); + + it('Render coordinate map and verify data config metrics panel "Field" contains only value which return either integer or float value', () => { + cy.get('[data-test-subj="comboBoxInput"]').eq(3).click(); + cy.get('.euiComboBoxOption__content').contains('AvgTicketPrice').should('exist'); + cy.get('.euiComboBoxOption__content').contains('DistanceMiles').should('exist'); + cy.get('.euiComboBoxOption__content').should('not.contain', 'DestLocation'); + cy.get('.euiComboBoxOption__content').should('have.length', 6); + }); + + it('Render coordinate map and verify data config metric panel "Plot Label" contains a combination of string value and integer value', () => { + cy.get('[data-test-subj="comboBoxInput"]').eq(4).click(); + cy.get('.euiComboBoxOption__content').contains('AvgTicketPrice').should('exist'); + cy.get('.euiComboBoxOption__content').contains('Dest').should('exist'); + cy.get('.euiComboBoxOption__content').contains('DestLocation').should('exist'); + }); +}); + +describe('Render coordinate map for panel options', () => { + beforeEach(() => { + renderCoordinateMap(); + renderDataForCoordinateMap(); + }); + + it('Render coordinate map and verify the title gets updated according to user input ', () => { + cy.get('input[name="title"]').type("coordinate map"); + cy.get('textarea[name="description"]').should('exist').click(); + cy.get('.gtitle').contains('coordinate map').should('exist'); + }); +}); + +describe('Render coordinate map for text', () => { + beforeEach(() => { + renderCoordinateMap(); + renderDataForCoordinateMap(); + }); + + it('Render coordinate map and verify by default the "Show" is enabled for "Show Text"', () => { + cy.get('[data-text="Show"]').should('have.text', 'Show'); + cy.get('[data-text="Show"] [data-test-subj="show"]').should('have.attr', 'checked'); + cy.get('[data-unformatted="Duluth International Airport"]').should('exist'); + }); + + it('Render coordinate map and change "Show Text" to "Hidden"', () => { + cy.get('[data-text="Hidden"]').should('have.text', 'Hidden').click(); + cy.get('[data-text="Hidden"] [data-test-subj="hidden"]').should('not.have.attr', 'checked'); + cy.get('[data-unformatted="Duluth International Airport"]').should('not.exist'); + }); + + it('Render coordinate map and verify by default the "Top" is enabled for "Position"', () => { + cy.get('[data-text="Top"]').should('have.text', 'Top'); + cy.get('[data-text="Top"] [data-test-subj="top center"]').should('have.attr', 'checked'); + }); + + it('Render coordinate map and change "Position" to "Right", "Bottom" and "Left"', () => { + cy.get('[data-text="Right"]').should('have.text', 'Right').click(); + cy.get('[data-text="Right"] [data-test-subj="middle right"]').should('not.have.attr', 'checked'); + cy.get('[data-text="Bottom"]').should('have.text', 'Bottom').click(); + cy.get('[data-text="Bottom"] [data-test-subj="bottom center"]').should('not.have.attr', 'checked'); + cy.get('[data-text="Left"]').should('have.text', 'Left').click(); + cy.get('[data-text="Left"] [data-test-subj="middle left"]').should('not.have.attr', 'checked'); + }); +}); + +describe('Render coordinate map for chart style options', () => { + beforeEach(() => { + renderCoordinateMap(); + renderDataForCoordinateMap(); + }); + + it('Render coordinate map and change Label Size ', () => { + cy.get('[data-test-subj="valueFieldNumber"]').click().type(labelSize); + cy.get('textarea[name="description"]').should('exist').click(); + cy.get('[data-unformatted="Duluth International Airport"]').should('have.css', 'font-size', '20px'); + cy.get('[data-test-subj="valueFieldNumber"]').should('have.value', labelSize) + }); + + it('Render coordinate map and change "Latitude Range"', () => { + cy.get('input[type="number"]').eq(1).should('have.value', latitudeRangeMin); + cy.get('input[type="number"]').eq(2).should('have.value', latitudeRangeMax); + cy.get('input[type="number"]').eq(1).click().clear().type(30); + }); + + it('Render coordinate map and change "Longitude Range"', () => { + cy.get('input[type="number"]').eq(3).should('have.value', longitudeRangeMin); + cy.get('input[type="number"]').eq(4).should('have.value', longitudeRangeMax); + cy.get('input[type="number"]').eq(4).click().clear().type(40); + }); +}); + +describe('Render coordinate map and verify if reset works properly', () => { + beforeEach(() => { + renderCoordinateMap(); + renderDataForCoordinateMap(); + }); + + it('Render coordinate map with all feild data then click on reset and verify reset works properly', () => { + cy.get('input[placeholder="Title"]').type('coordinate map'); + cy.get('textarea[placeholder="Description"]').type('Description For coordinate map'); + cy.get('.euiButton__text').contains('Hidden').click(); + cy.get('.euiButton__text').contains('Right').click(); + cy.get('[data-test-subj="valueFieldNumber"]').click().type(labelSize); + cy.get('.euiButtonEmpty__text').contains('Reset').click(); + cy.get('input[placeholder="Title"]').should('not.have.value', 'coordinate map'); + cy.get('textarea[placeholder="Description"]').should('not.have.value', 'Description For coordinate map'); + cy.get('[data-text="Show"] [data-test-subj="show"]').should('have.attr', 'checked'); + cy.get('[data-text="Top"] [data-test-subj="top center"]').should('have.attr', 'checked'); + cy.get('[data-test-subj="valueFieldNumber"]').should('have.value', ''); + }); +}); diff --git a/dashboards-observability/.cypress/utils/constants.js b/dashboards-observability/.cypress/utils/constants.js index 75e343086..d67d3988f 100644 --- a/dashboards-observability/.cypress/utils/constants.js +++ b/dashboards-observability/.cypress/utils/constants.js @@ -60,6 +60,8 @@ export const setTimeFilter = (setEndTime = false, refresh = true) => { // notebooks export const TEST_NOTEBOOK = 'Test Notebook'; export const SAMPLE_URL = 'https://github.com/opensearch-project/sql/tree/main/sql-jdbc'; +export const NOTEBOOK_TEXT = 'Use Notebooks to interactively and collaboratively develop rich reports backed by live data. Common use cases for notebooks includes creating postmortem reports, designing run books, building live infrastructure reports, or even documentation.'; +export const OPENSEARCH_URL = 'https://opensearch.org/docs/latest/observability-plugin/notebooks/'; export const MARKDOWN_TEXT = `%md # Heading 1 @@ -100,3 +102,22 @@ export const supressResizeObserverIssue = () => { if (err.message.includes('ResizeObserver loop')) return false; }); }; + +export const verify_traces_spans_data_grid_cols_exists = () => { + cy.get('.euiDataGridHeaderCell__content').contains('Span ID').should('exist'); + cy.get('.euiDataGridHeaderCell__content').contains('Trace ID').should('exist'); + cy.get('.euiDataGridHeaderCell__content').contains('Operation').should('exist'); + cy.get('.euiDataGridHeaderCell__content').contains('Duration').should('exist'); + cy.get('.euiDataGridHeaderCell__content').contains('Start time').should('exist'); + cy.get('.euiDataGridHeaderCell__content').contains('End time').should('exist'); + cy.get('.euiDataGridHeaderCell__content').contains('Errors').should('exist'); +} + +export const count_table_row = (expected_row_count) => { + cy.get('.euiDataGridHeader [role="columnheader"]').then($el => { + let colmun_header_count = Cypress.$($el).length; + let table_grid_cell_count = Cypress.$('[data-test-subj="dataGridRowCell"]').length; + const total_row_count = table_grid_cell_count / colmun_header_count; + expect(total_row_count).to.equal(expected_row_count) + }); +} diff --git a/dashboards-observability/.cypress/utils/event_constants.js b/dashboards-observability/.cypress/utils/event_constants.js index 130d32590..9e0f89697 100644 --- a/dashboards-observability/.cypress/utils/event_constants.js +++ b/dashboards-observability/.cypress/utils/event_constants.js @@ -3,30 +3,53 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { supressResizeObserverIssue } from './constants' +import { supressResizeObserverIssue } from './constants'; export const delay = 1000; -export const YEAR_TO_DATE_DOM_ID = '[data-test-subj="superDatePickerCommonlyUsed_Year_to date"]' +export const YEAR_TO_DATE_DOM_ID = '[data-test-subj="superDatePickerCommonlyUsed_Year_to date"]'; export const TEST_QUERIES = [ { query: 'source = opensearch_dashboards_sample_data_flights', - dateRangeDOM: YEAR_TO_DATE_DOM_ID + dateRangeDOM: YEAR_TO_DATE_DOM_ID, }, { - query: 'source = opensearch_dashboards_sample_data_flights | stats avg(FlightDelayMin) by Carrier', - dateRangeDOM: YEAR_TO_DATE_DOM_ID + query: + 'source = opensearch_dashboards_sample_data_flights | stats avg(FlightDelayMin) by Carrier', + dateRangeDOM: YEAR_TO_DATE_DOM_ID, }, { - query: 'source = opensearch_dashboards_sample_data_logs' + query: 'source = opensearch_dashboards_sample_data_logs', }, { - query: 'source = opensearch_dashboards_sample_data_logs | stats count() by host', - dateRangeDOM: YEAR_TO_DATE_DOM_ID + query: + 'source=opensearch_dashboards_sample_data_flights | stats max(AvgTicketPrice) by DestCountry, DestCityName, Carrier', + dateRangeDOM: YEAR_TO_DATE_DOM_ID, }, { - query: 'source = opensearch_dashboards_sample_data_logs | stats count(), avg(bytes) by host, tags', - dateRangeDOM: YEAR_TO_DATE_DOM_ID + query: + 'source = opensearch_dashboards_sample_data_logs | stats count(), avg(bytes) by host, tags', + dateRangeDOM: YEAR_TO_DATE_DOM_ID, + }, + { + query: + 'source=opensearch_dashboards_sample_data_flights | stats avg(FlightDelayMin) by DestCountry, DestCityName', + dateRangeDOM: YEAR_TO_DATE_DOM_ID, + }, + { + query: + "source = opensearch_dashboards_sample_data_logs | where response='503' or response='404' | stats count() by span(timestamp,1d)", + dateRangeDOM: YEAR_TO_DATE_DOM_ID, + }, + { + query: + 'source=opensearch_dashboards_sample_data_flights |where FlightDelayMin > 0 | stats sum(FlightDelayMin) as total_delay_min, count() as total_delayed by Carrier |eval avg_delay=total_delay_min / total_delayed | sort - avg_delay', + dateRangeDOM: YEAR_TO_DATE_DOM_ID, + }, + { + query: + 'source = opensearch_dashboards_sample_data_logs | stats count(), max(bytes) by span(timestamp,1d), clientip, host', + dateRangeDOM: YEAR_TO_DATE_DOM_ID, }, ]; @@ -36,6 +59,18 @@ export const SAVE_QUERY2 = 'Mock Flight count by destination'; export const SAVE_QUERY3 = 'Mock Flight count by destination save to panel'; export const SAVE_QUERY4 = 'Mock Flight peek'; +export const aggregationValues = [ + 'COUNT', + 'SUM', + 'AVERAGE', + 'MAX', + 'MIN', + 'VAR_SAMP', + 'VAR_POP', + 'STDDEV_SAMP', + 'STDDEV_POP', +]; + export const querySearch = (query, rangeSelected) => { cy.get('[data-test-subj="searchAutocompleteTextArea"]').type(query); cy.get('[data-test-subj="superDatePickerToggleQuickMenuButton"]').click(); @@ -70,4 +105,146 @@ export const landOnPanels = () => { `${Cypress.env('opensearchDashboards')}/app/observability-dashboards#/operational_panels` ); cy.wait(delay); -}; \ No newline at end of file +}; + +const vis_name_sub_string = Math.floor(Math.random() * 100); +export const saveVisualizationAndVerify = () => { + cy.get('[data-test-subj="eventExplorer__saveManagementPopover"]').click(); + cy.get('[data-test-subj="eventExplorer__querySaveComboBox"]').click(); + cy.get('.euiComboBoxOptionsList__rowWrap .euiFilterSelectItem').eq(0).click(); + cy.get( + '.euiPopover__panel .euiFormControlLayoutIcons [data-test-subj="comboBoxToggleListButton"]' + ) + .eq(0) + .click(); + cy.get('.euiPopover__panel input') + .eq(1) + .type(`Test visualization` + vis_name_sub_string); + cy.get('[data-test-subj="eventExplorer__querySaveConfirm"]').click(); + cy.wait(delay); + cy.get('.euiHeaderBreadcrumbs a').eq(1).click(); + cy.get('.euiFlexGroup .euiFormControlLayout__childrenWrapper input') + .eq(0) + .type(`Test visualization` + vis_name_sub_string) + .type('{enter}'); + cy.get('.euiBasicTable .euiTableCellContent button').eq(0).click(); +}; + +export const deleteVisualization = () => { + cy.get('a[href = "#/event_analytics"]').click(); + cy.get('.euiFlexGroup .euiFormControlLayout__childrenWrapper input') + .eq(0) + .type(`Test visualization` + vis_name_sub_string) + .type('{enter}'); + cy.get('input[data-test-subj = "checkboxSelectAll"]').click(); + cy.get('.euiButtonContent.euiButtonContent--iconRight.euiButton__content').click(); + cy.get('.euiContextMenuItem .euiContextMenuItem__text').eq(0).click(); + cy.get('input[placeholder = "delete"]').clear().type('delete'); + cy.get('button[data-test-subj = "popoverModal__deleteButton"]').click(); + cy.get('.euiToastHeader').should('exist'); +}; + +export const renderTreeMapchart = () => { + querySearch(TEST_QUERIES[7].query, TEST_QUERIES[7].dateRangeDOM); + cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]') + .type('Tree Map') + .type('{enter}'); + cy.get('#configPanel__panelOptions .euiFieldText').click().type('Tree Map'); + cy.get('.euiFlexItem .euiFormRow [placeholder="Description"]') + .click() + .type('This is the description for Tree Map'); + cy.get('.euiIEFlexWrapFix').eq(1).contains('Treemap').should('exist'); + cy.get('#configPanel__treemap_options').contains('Tiling Algorithm').should('exist'); + cy.get('[data-test-subj = "comboBoxInput"]').eq(3).click(); + cy.get('button[name="Slice Dice"]').click(); +}; + +export const renderPieChart = () => { + querySearch(TEST_QUERIES[5].query, TEST_QUERIES[5].dateRangeDOM); + cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]').click(); + cy.get('[data-test-subj="comboBoxOptionsList "] button span').contains('Pie').click(); + cy.wait(delay); + cy.get('#configPanel__panelOptions .euiFieldText').click().type('Pie chart'); + cy.get('.euiFlexItem .euiFormRow [placeholder="Description"]') + .click() + .type('This is the description for Pie chart'); + cy.get('[aria-controls="configPanel__legend"]').contains('Legend').should('exist'); + cy.get('#configPanel__legend .euiTitle.euiTitle--xxsmall').eq(0).contains('Show Legend'); + cy.get('span[data-text="Show"]').contains('Show').should('exist'); + cy.get('#configPanel__legend .euiTitle.euiTitle--xxsmall').eq(1).contains('Position'); + cy.get('span[data-text="Right"]').contains('Right').should('exist'); + cy.get('#configPanel__legend .euiTitle.euiTitle--xxsmall').eq(2).contains('Legend Size'); + cy.get('[aria-controls="configPanel__chartStyles"]').contains('Chart Styles').should('exist'); + cy.get('#configPanel__chartStyles .euiTitle.euiTitle--xxsmall').eq(0).contains('Mode').click(); + cy.get( + '#configPanel__chartStyles .euiComboBox__inputWrap.euiComboBox__inputWrap--noWrap.euiComboBox__inputWrap-isClearable' + ).click(); + cy.get('.euiComboBoxOption__content').contains('Donut').click(); + cy.get('#configPanel__chartStyles .euiTitle.euiTitle--xxsmall').eq(1).contains('Label Size'); + cy.get('#configPanel__chartStyles input[type="number"]').click().type('10'); + cy.get('#configPanel__chartStyles .euiTitle.euiTitle--xxsmall').eq(2).contains('Color Theme'); + cy.get('.euiSuperSelectControl').click(); + cy.get('.euiColorPalettePicker__item').eq(1).contains('Single Color').click(); + cy.get('.euiFieldText.euiColorPicker__input.euiFieldText--withIcon').click(); + cy.get('[aria-label="Select #D36086 as the color"]').click(); + cy.get('.visEditorSidebar__controls [data-test-subj="visualizeEditorRenderButton"]') + .contains('Preview') + .click(); + cy.get('.plot-container.plotly').should('exist'); +}; + +export const renderDataConfig = () => { + cy.get('.euiResizablePanel.euiResizablePanel--middle').contains('Data Cofigurations'); + cy.get('.euiTitle.euiTitle--xxsmall').eq(1).contains('Dimensions').should('exist'); + cy.get('.first-division .euiFormLabel.euiFormRow__label').eq(0).contains('Aggregation'); + cy.get('[data-test-subj="comboBoxSearchInput"]').eq(0).click(); + cy.get('.euiComboBoxOption__content').eq(2).click(); + cy.get('.first-division .euiFormLabel.euiFormRow__label').eq(1).contains('Field'); + cy.get('[data-test-subj="comboBoxSearchInput"]').eq(1).click(); + cy.get('.euiComboBoxOption__content').eq(1).click(); + cy.get('.euiFieldText[placeholder="Custom label"]').eq(0).type('Average field'); + cy.get('.euiTitle.euiTitle--xxsmall').eq(2).contains('Metrics').should('exist'); + cy.get('.first-division .euiFormLabel.euiFormRow__label').eq(0).contains('Aggregation'); + cy.get('.euiFormRow__fieldWrapper .euiComboBox').eq(2).click(); + cy.get('.euiComboBoxOption__content').eq(4).click(); + cy.get('.first-division .euiFormLabel.euiFormRow__label').eq(4).click(); + cy.get('.euiComboBoxOption__content').eq(0).click(); + cy.get('.euiFieldText[placeholder="Custom label"]').eq(1).type('Min field'); + cy.get('.euiButton__text').contains('Right').click(); + cy.get('[data-test-subj="visualizeEditorRenderButton"]').contains('Update chart').click(); + cy.get('.js-plotly-plot').should('exist'); +}; + +export const renderLineChart = () => { + landOnEventVisualizations(); + querySearch(TEST_QUERIES[5].query, TEST_QUERIES[5].dateRangeDOM); + cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]') + .type('Line') + .type('{enter}'); +}; + +export const renderAddParent = () => { + cy.get(' [data-test-subj="addParentButton"] .euiButton__text').contains('+ Add Parent').click(); + cy.get('.first-division .euiFormLabel.euiFormRow__label').contains('Parent 1').should('exist'); + cy.get('p.euiComboBoxPlaceholder').eq(0).click({ force: true }); + cy.get('.euiComboBoxOption__content').eq(0).click(); + cy.get(' [data-test-subj="addParentButton"] .euiButton__text').contains('+ Add Parent').click(); + cy.get('.first-division .euiFormLabel.euiFormRow__label').contains('Parent 2').should('exist'); + cy.get('p.euiComboBoxPlaceholder').click({ force: true }); + cy.get('.euiComboBoxOption__content').eq(1).click(); + cy.get(' [data-test-subj="addParentButton"] .euiButton__text').contains('+ Add Parent').click(); + cy.get('.first-division .euiFormLabel.euiFormRow__label').contains('Parent 3').should('exist'); + cy.get('p.euiComboBoxPlaceholder').click({ force: true }); + cy.get('.euiComboBoxOption__content').eq(2).click(); + cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]') + .type('Line') + .type('{enter}'); +}; + +export const renderGaugeChart = () => { + landOnEventVisualizations(); + querySearch(TEST_QUERIES[1].query, TEST_QUERIES[1].dateRangeDOM); + cy.get('[data-test-subj="configPane__vizTypeSelector"] [data-test-subj="comboBoxInput"]') + .type('Gauge') + .type('{enter}'); +}; diff --git a/dashboards-observability/.gitignore b/dashboards-observability/.gitignore index c0fc79791..bf5586d64 100644 --- a/dashboards-observability/.gitignore +++ b/dashboards-observability/.gitignore @@ -4,3 +4,4 @@ build/ coverage/ .cypress/screenshots .cypress/videos +common/query_manager/antlr/output diff --git a/dashboards-observability/common/constants/colors.ts b/dashboards-observability/common/constants/colors.ts new file mode 100644 index 000000000..76cf9c9f1 --- /dev/null +++ b/dashboards-observability/common/constants/colors.ts @@ -0,0 +1,186 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { colorPalette } from '@elastic/eui'; + +export const BLUES_PALETTE = { + name: 'Blues', + label: 'Blues', + colors: [ + 'rgb(5,10,172)', + 'rgb(40,60,190)', + 'rgb(70,100,245)', + 'rgb(90,120,245)', + 'rgb(106,137,247)', + 'rgb(220,220,220)', + ], +}; + +export const REDS_PALETTE = { + name: 'Reds', + label: 'Reds', + colors: ['rgb(220,220,220)', 'rgb(245,195,157)', 'rgb(245,160,105)', 'rgb(178,10,28)'], +}; + +export const GREENS_PALETTE = { + name: 'Greens', + label: 'Greens', + colors: [ + 'rgb(0,68,27)', + 'rgb(0,109,44)', + 'rgb(35,139,69)', + 'rgb(65,171,93)', + 'rgb(116,196,118)', + 'rgb(161,217,155)', + 'rgb(199,233,192)', + 'rgb(229,245,224)', + 'rgb(247,252,245)', + ], +}; + +export const GREYS_PALETTE = { + name: 'Greys', + label: 'Greys', + colors: ['rgb(0,0,0)', 'rgb(255,255,255)'], +}; + +export const BLUE_RED_PALETTE = { + name: 'Bluered', + label: 'Blue-Red', + colors: ['rgb(0,0,255)', 'rgb(255,0,0)'], +}; + +export const RED_BLUE_PALETTE = { + name: 'RdBu', + label: 'Red-Blue', + colors: [ + 'rgb(5,10,172)', + 'rgb(106,137,247)', + 'rgb(190,190,190)', + 'rgb(220,170,132)', + 'rgb(230,145,90)', + 'rgb(178,10,28)', + ], +}; + +export const YELLOW_ORANGE_RED_PALETTE = { + name: 'YlOrRd', + label: 'Yellow-Orange-Red', + colors: [ + 'rgb(128,0,38)', + 'rgb(189,0,38)', + 'rgb(227,26,28)', + 'rgb(252,78,42)', + 'rgb(253,141,60)', + 'rgb(254,178,76)', + 'rgb(254,217,118)', + 'rgb(255,237,160)', + 'rgb(255,255,204)', + ], +}; + +export const YELLOW_GREEN_BLUE_PALETTE = { + name: 'YlGnBu', + label: 'Yellow-Green-Blue', + colors: [ + 'rgb(8,29,88)', + 'rgb(37,52,148)', + 'rgb(34,94,168)', + 'rgb(29,145,192)', + 'rgb(65,182,196)', + 'rgb(127,205,187)', + 'rgb(199,233,180)', + 'rgb(237,248,217)', + 'rgb(255,255,217)', + ], +}; + +export const DEFAULT_PALETTE = 'default'; +export const SINGLE_COLOR_PALETTE = 'singleColor'; +export const MULTI_COLOR_PALETTE = 'multicolor'; + +export const COLOR_PALETTES = [ + { + value: DEFAULT_PALETTE, + title: 'Default', + type: 'text', + }, + { + value: SINGLE_COLOR_PALETTE, + title: 'Single color', + type: 'text', + }, + { + value: MULTI_COLOR_PALETTE, + title: 'Multicolored', + type: 'text', + }, + { + value: BLUES_PALETTE.name, + title: BLUES_PALETTE.label, + palette: colorPalette(BLUES_PALETTE.colors, 20), + type: 'gradient', + }, + { + value: REDS_PALETTE.name, + title: REDS_PALETTE.label, + palette: colorPalette(REDS_PALETTE.colors, 20), + type: 'gradient', + }, + { + value: GREENS_PALETTE.name, + title: GREENS_PALETTE.label, + palette: colorPalette(GREENS_PALETTE.colors, 20), + type: 'gradient', + }, + { + value: GREYS_PALETTE.name, + title: GREYS_PALETTE.label, + palette: colorPalette(GREYS_PALETTE.colors, 20), + type: 'gradient', + }, + { + value: BLUE_RED_PALETTE.name, + title: BLUE_RED_PALETTE.label, + palette: colorPalette(BLUE_RED_PALETTE.colors, 20), + type: 'gradient', + }, + { + value: RED_BLUE_PALETTE.name, + title: RED_BLUE_PALETTE.label, + palette: colorPalette(RED_BLUE_PALETTE.colors, 20, true), + type: 'gradient', + }, + { + value: YELLOW_ORANGE_RED_PALETTE.name, + title: YELLOW_ORANGE_RED_PALETTE.label, + palette: colorPalette(YELLOW_ORANGE_RED_PALETTE.colors, 20), + type: 'gradient', + }, + { + value: YELLOW_GREEN_BLUE_PALETTE.name, + title: YELLOW_GREEN_BLUE_PALETTE.label, + palette: colorPalette(YELLOW_GREEN_BLUE_PALETTE.colors, 20), + type: 'gradient', + }, +]; +export const HEX_CONTRAST_COLOR = 0xFFFFFF; +export const PIE_PALETTES = [ + { + value: DEFAULT_PALETTE, + title: 'Default', + type: 'text', + }, + { + value: SINGLE_COLOR_PALETTE, + title: 'Single Color', + type: 'text', + } +]; + +export const HEATMAP_PALETTE_COLOR = { name: REDS_PALETTE.label, color: REDS_PALETTE.label }; +export const HEATMAP_SINGLE_COLOR = { name: 'singleColor', color: '#000000' }; +export const OPACITY = 'opacity'; +export const SPECTRUM = 'spectrum'; diff --git a/dashboards-observability/common/constants/data_table.ts b/dashboards-observability/common/constants/data_table.ts new file mode 100644 index 000000000..bbca653a7 --- /dev/null +++ b/dashboards-observability/common/constants/data_table.ts @@ -0,0 +1,16 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export const GRID_HEADER_COLUMN_MAX_WIDTH = '150px'; +export const GRID_PAGE_RANGE_DISPLAY = 5; +export const COLUMN_DEFAULT_MIN_WIDTH = 100; +export const GRID_PAGE_SIZES = [10, 50, 100]; +export const ROW_DENSITIES = [ + { icon: 'tableDensityExpanded', height: 55, selected: false }, + { icon: 'tableDensityNormal', height: 45, selected: false }, + { icon: 'tableDensityCompact', height: 35, selected: true }, +]; + +export const HEADER_HEIGHT = 35; diff --git a/dashboards-observability/common/constants/explorer.ts b/dashboards-observability/common/constants/explorer.ts index fbe09f13b..564c68167 100644 --- a/dashboards-observability/common/constants/explorer.ts +++ b/dashboards-observability/common/constants/explorer.ts @@ -3,6 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { visChartTypes } from './shared'; export const EVENT_ANALYTICS_DOCUMENTATION_URL = 'https://opensearch.org/docs/latest/observability-plugin/event-analytics/'; export const OPEN_TELEMETRY_LOG_CORRELATION_LINK = @@ -74,6 +75,80 @@ export const REDUX_EXPL_SLICE_FIELDS = 'fields'; export const REDUX_EXPL_SLICE_QUERY_TABS = 'queryTabs'; export const REDUX_EXPL_SLICE_VISUALIZATION = 'explorerVisualization'; export const REDUX_EXPL_SLICE_COUNT_DISTRIBUTION = 'countDistributionVisualization'; -export const PLOTLY_GAUGE_COLUMN_NUMBER = 5; +export const PLOTLY_GAUGE_COLUMN_NUMBER = 4; export const APP_ANALYTICS_TAB_ID_REGEX = /application-analytics-tab.+/; export const DEFAULT_AVAILABILITY_QUERY = 'stats count() by span( timestamp, 1h )'; +export const ADD_BUTTON_TEXT = '+ Add color theme'; + +export const VIZ_CONTAIN_XY_AXIS = [ + visChartTypes.Bar, + visChartTypes.Histogram, + visChartTypes.Line, + visChartTypes.Pie, + visChartTypes.Scatter, +]; + +// default ppl aggregation method options +export const AGGREGATION_OPTIONS = [ + { + label: 'count', + }, + { + label: 'sum', + }, + { + label: 'avg', + }, + { + label: 'max', + }, + { + label: 'min', + }, + { + label: 'var_samp', + }, + { + label: 'var_pop', + }, + { + label: 'stddev_samp', + }, + { + label: 'stddev_pop', + }, +]; + +// numeric fields type for metrics +export const numericalTypes = ['float', 'double', 'bigint', 'long', 'octet', 'short', 'byte', 'integer']; +// Data table constants +export const GRID_HEADER_COLUMN_MAX_WIDTH = '150px'; +export const GRID_PAGE_RANGE_DISPLAY = 5; +export const COLUMN_DEFAULT_MIN_WIDTH = 100; +export const GRID_PAGE_SIZES = [10, 50, 100]; +export const ROW_DENSITIES = [ + { icon: 'tableDensityExpanded', height: 55, selected: false }, + { icon: 'tableDensityNormal', height: 45, selected: false }, + { icon: 'tableDensityCompact', height: 35, selected: true }, +]; + +export const HEADER_HEIGHT = 35; + +// gauge chart default parameters +export interface DefaultGaugeChartParametersProps { + GaugeTitleSize: number, + DisplayDefaultGauges: number, + OrientationDefault: string, + TickLength: number, + LegendPlacement: string, + ThresholdsMaxLimit: number +}; + +export const DefaultGaugeChartParameters: DefaultGaugeChartParametersProps = { + GaugeTitleSize: 14, + DisplayDefaultGauges: 1, + OrientationDefault: 'h', + TickLength: 5, + LegendPlacement: 'center', + ThresholdsMaxLimit: 1 +} diff --git a/dashboards-observability/common/constants/shared.ts b/dashboards-observability/common/constants/shared.ts index 19c0fb8fd..e61909789 100644 --- a/dashboards-observability/common/constants/shared.ts +++ b/dashboards-observability/common/constants/shared.ts @@ -3,6 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { IField } from '../../common/types/explorer'; import CSS from 'csstype'; // Client route @@ -71,57 +72,120 @@ export const pageStyles: CSS.Properties = { maxWidth: '1130px', }; +export enum visChartTypes { + Bar = 'bar', + HorizontalBar = 'horizontal_bar', + Line = 'line', + Pie = 'pie', + HeatMap = 'heatmap', + Text = 'text', + Gauge = 'gauge', + Histogram = 'histogram', + TreeMap = 'tree_map', + Scatter = 'scatter', + LogsView = 'logs_view', +} + +export interface ValueOptionsAxes { + xaxis?: IField[]; + yaxis?: IField[]; + zaxis?: IField[]; + childField?: IField[]; + valueField?: IField[]; + series?: IField[]; + value?: IField[]; +} + export const NUMERICAL_FIELDS = ['short', 'integer', 'long', 'float', 'double']; -export const ENABLED_VIS_TYPES = ['bar', 'horizontal_bar', 'line', 'pie', 'heatmap', 'text']; +export const ENABLED_VIS_TYPES = [ + visChartTypes.Bar, + visChartTypes.HorizontalBar, + visChartTypes.Line, + visChartTypes.Pie, + visChartTypes.HeatMap, + visChartTypes.Text, + visChartTypes.TreeMap, + visChartTypes.Gauge, + visChartTypes.Histogram, + visChartTypes.Scatter, + visChartTypes.LogsView, +]; //Live tail constants export const LIVE_OPTIONS = [ { - label:'5s', + label: '5s', startTime: 'now-5s', delayTime: 5000, }, { - label:'10s', + label: '10s', startTime: 'now-10s', delayTime: 10000, }, { - label:'30s', + label: '30s', startTime: 'now-30s', delayTime: 30000, }, { - label:'1m', + label: '1m', startTime: 'now-1m', delayTime: 60000, }, { - label:'5m', + label: '5m', startTime: 'now-5m', delayTime: 60000 * 5, }, { - label:'15m', + label: '15m', startTime: 'now-15m', delayTime: 60000 * 15, }, { - label:'30m', + label: '30m', startTime: 'now-30m', delayTime: 60000 * 30, }, { - label:'1h', + label: '1h', startTime: 'now-1h', delayTime: 60000 * 60, }, { - label:'2h', + label: '2h', startTime: 'now-2h', delayTime: 60000 * 120, }, ]; -export const LIVE_END_TIME ='now'; \ No newline at end of file +export const LIVE_END_TIME = 'now'; +export interface DefaultChartStylesProps { + DefaultModeLine: string; + Interpolation: string; + LineWidth: number; + FillOpacity: number; + MarkerSize: number; + ShowLegend: string; + LegendPosition: string; + LabelAngle: number; + DefaultSortSectors: string; + DefaultModeScatter: string; +} + +export const DefaultChartStyles: DefaultChartStylesProps = { + DefaultModeLine: 'lines', + Interpolation: 'spline', + LineWidth: 2, + FillOpacity: 40, + MarkerSize: 5, + ShowLegend: 'show', + LegendPosition: 'v', + LabelAngle: 0, + DefaultSortSectors: 'largest_to_smallest', + DefaultModeScatter: 'markers', +}; + +export const FILLOPACITY_DIV_FACTOR = 200; diff --git a/dashboards-observability/common/query_manager/antlr/adaptors/case_insensitive_char_stream.ts b/dashboards-observability/common/query_manager/antlr/adaptors/case_insensitive_char_stream.ts new file mode 100644 index 000000000..6c3414f35 --- /dev/null +++ b/dashboards-observability/common/query_manager/antlr/adaptors/case_insensitive_char_stream.ts @@ -0,0 +1,60 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { CharStream } from 'antlr4ts'; + +export class CaseInsensitiveCharStream { + private stream: CharStream; + + get index(): number { + return this.stream.index; + } + + get size(): number { + return this.stream.size; + } + + get sourceName(): string { + return 'pplquery'; + } + + constructor(stream: CharStream) { + this.stream = stream; + } + + LA(offset: number): number { + const c: number = this.stream.LA(offset); + if (c <= 0) { + return c; + } + + // case insensitivity support for PPL + return String.fromCodePoint(c).toUpperCase().codePointAt(0)!; + } + + consume(): void { + this.stream.consume(); + } + + mark(): number { + return this.stream.mark(); + } + + release(marker: number): void { + this.stream.release(marker); + } + + seek(index: number): void { + this.stream.seek(index); + } + + getText(interval: any): string { + return this.stream.getText(interval); + } + + toString(): string { + return this.stream.toString(); + } +} diff --git a/dashboards-observability/common/query_manager/antlr/grammar/.antlr/OpenSearchPPLLexer.interp b/dashboards-observability/common/query_manager/antlr/grammar/.antlr/OpenSearchPPLLexer.interp new file mode 100644 index 000000000..68b2f0fd1 --- /dev/null +++ b/dashboards-observability/common/query_manager/antlr/grammar/.antlr/OpenSearchPPLLexer.interp @@ -0,0 +1,831 @@ +token literal names: +null +'SEARCH' +'FROM' +'WHERE' +'FIELDS' +'RENAME' +'STATS' +'DEDUP' +'SORT' +'EVAL' +'HEAD' +'TOP' +'RARE' +'PARSE' +'KMEANS' +'AD' +'AS' +'BY' +'SOURCE' +'INDEX' +'D' +'DESC' +'SORTBY' +'AUTO' +'STR' +'IP' +'NUM' +'KEEPEMPTY' +'CONSECUTIVE' +'DEDUP_SPLITVALUES' +'PARTITIONS' +'ALLNUM' +'DELIM' +'CENTROIDS' +'ITERATIONS' +'DISTANCE_TYPE' +'NUMBER_OF_TREES' +'SHINGLE_SIZE' +'SAMPLE_SIZE' +'OUTPUT_AFTER' +'TIME_DECAY' +'ANOMALY_RATE' +'TIME_FIELD' +'TIME_ZONE' +'TRAINING_DATA_SIZE' +'ANOMALY_SCORE_THRESHOLD' +'CASE' +'IN' +'NOT' +'OR' +'AND' +'XOR' +'TRUE' +'FALSE' +'REGEXP' +'DATETIME' +'INTERVAL' +'MICROSECOND' +'MILLISECOND' +'SECOND' +'MINUTE' +'HOUR' +'DAY' +'WEEK' +'MONTH' +'QUARTER' +'YEAR' +'SECOND_MICROSECOND' +'MINUTE_MICROSECOND' +'MINUTE_SECOND' +'HOUR_MICROSECOND' +'HOUR_SECOND' +'HOUR_MINUTE' +'DAY_MICROSECOND' +'DAY_SECOND' +'DAY_MINUTE' +'DAY_HOUR' +'YEAR_MONTH' +'DATAMODEL' +'LOOKUP' +'SAVEDSEARCH' +'INT' +'INTEGER' +'DOUBLE' +'LONG' +'FLOAT' +'STRING' +'BOOLEAN' +'|' +',' +'.' +'=' +'>' +'<' +null +null +null +'+' +'-' +'*' +'/' +'%' +'!' +':' +'(' +')' +'[' +']' +'\'' +'"' +'`' +'~' +'&' +'^' +'AVG' +'COUNT' +'DISTINCT_COUNT' +'ESTDC' +'ESTDC_ERROR' +'MAX' +'MEAN' +'MEDIAN' +'MIN' +'MODE' +'RANGE' +'STDEV' +'STDEVP' +'SUM' +'SUMSQ' +'VAR_SAMP' +'VAR_POP' +'STDDEV_SAMP' +'STDDEV_POP' +'PERCENTILE' +'FIRST' +'LAST' +'LIST' +'VALUES' +'EARLIEST' +'EARLIEST_TIME' +'LATEST' +'LATEST_TIME' +'PER_DAY' +'PER_HOUR' +'PER_MINUTE' +'PER_SECOND' +'RATE' +'SPARKLINE' +'C' +'DC' +'ABS' +'CEIL' +'CEILING' +'CONV' +'CRC32' +'E' +'EXP' +'FLOOR' +'LN' +'LOG' +'LOG10' +'LOG2' +'MOD' +'PI' +'POW' +'POWER' +'RAND' +'ROUND' +'SIGN' +'SQRT' +'TRUNCATE' +'ACOS' +'ASIN' +'ATAN' +'ATAN2' +'COS' +'COT' +'DEGREES' +'RADIANS' +'SIN' +'TAN' +'ADDDATE' +'DATE' +'DATE_ADD' +'DATE_SUB' +'DAYOFMONTH' +'DAYOFWEEK' +'DAYOFYEAR' +'DAYNAME' +'FROM_DAYS' +'MONTHNAME' +'SUBDATE' +'TIME' +'TIME_TO_SEC' +'TIMESTAMP' +'DATE_FORMAT' +'TO_DAYS' +'SUBSTR' +'SUBSTRING' +'LTRIM' +'RTRIM' +'TRIM' +'TO' +'LOWER' +'UPPER' +'CONCAT' +'CONCAT_WS' +'LENGTH' +'STRCMP' +'RIGHT' +'LEFT' +'ASCII' +'LOCATE' +'REPLACE' +'CAST' +'LIKE' +'ISNULL' +'ISNOTNULL' +'IFNULL' +'NULLIF' +'IF' +'MATCH' +'MATCH_PHRASE' +'SIMPLE_QUERY_STRING' +'ALLOW_LEADING_WILDCARD' +'ANALYZE_WILDCARD' +'ANALYZER' +'AUTO_GENERATE_SYNONYMS_PHRASE_QUERY' +'BOOST' +'CUTOFF_FREQUENCY' +'DEFAULT_FIELD' +'DEFAULT_OPERATOR' +'ENABLE_POSITION_INCREMENTS' +'FLAGS' +'FUZZY_MAX_EXPANSIONS' +'FUZZY_PREFIX_LENGTH' +'FUZZY_TRANSPOSITIONS' +'FUZZY_REWRITE' +'FUZZINESS' +'LENIENT' +'LOW_FREQ_OPERATOR' +'MAX_DETERMINIZED_STATES' +'MAX_EXPANSIONS' +'MINIMUM_SHOULD_MATCH' +'OPERATOR' +'PHRASE_SLOP' +'PREFIX_LENGTH' +'QUOTE_ANALYZER' +'QUOTE_FIELD_SUFFIX' +'REWRITE' +'SLOP' +'TIE_BREAKER' +'TYPE' +'ZERO_TERMS_QUERY' +'SPAN' +'MS' +'S' +'M' +'H' +'W' +'Q' +'Y' +null +null +null +null +null +null +null +null + +token symbolic names: +null +SEARCH +FROM +WHERE +FIELDS +RENAME +STATS +DEDUP +SORT +EVAL +HEAD +TOP +RARE +PARSE +KMEANS +AD +AS +BY +SOURCE +INDEX +D +DESC +SORTBY +AUTO +STR +IP +NUM +KEEPEMPTY +CONSECUTIVE +DEDUP_SPLITVALUES +PARTITIONS +ALLNUM +DELIM +CENTROIDS +ITERATIONS +DISTANCE_TYPE +NUMBER_OF_TREES +SHINGLE_SIZE +SAMPLE_SIZE +OUTPUT_AFTER +TIME_DECAY +ANOMALY_RATE +TIME_FIELD +TIME_ZONE +TRAINING_DATA_SIZE +ANOMALY_SCORE_THRESHOLD +CASE +IN +NOT +OR +AND +XOR +TRUE +FALSE +REGEXP +DATETIME +INTERVAL +MICROSECOND +MILLISECOND +SECOND +MINUTE +HOUR +DAY +WEEK +MONTH +QUARTER +YEAR +SECOND_MICROSECOND +MINUTE_MICROSECOND +MINUTE_SECOND +HOUR_MICROSECOND +HOUR_SECOND +HOUR_MINUTE +DAY_MICROSECOND +DAY_SECOND +DAY_MINUTE +DAY_HOUR +YEAR_MONTH +DATAMODEL +LOOKUP +SAVEDSEARCH +INT +INTEGER +DOUBLE +LONG +FLOAT +STRING +BOOLEAN +PIPE +COMMA +DOT +EQUAL +GREATER +LESS +NOT_GREATER +NOT_LESS +NOT_EQUAL +PLUS +MINUS +STAR +DIVIDE +MODULE +EXCLAMATION_SYMBOL +COLON +LT_PRTHS +RT_PRTHS +LT_SQR_PRTHS +RT_SQR_PRTHS +SINGLE_QUOTE +DOUBLE_QUOTE +BACKTICK +BIT_NOT_OP +BIT_AND_OP +BIT_XOR_OP +AVG +COUNT +DISTINCT_COUNT +ESTDC +ESTDC_ERROR +MAX +MEAN +MEDIAN +MIN +MODE +RANGE +STDEV +STDEVP +SUM +SUMSQ +VAR_SAMP +VAR_POP +STDDEV_SAMP +STDDEV_POP +PERCENTILE +FIRST +LAST +LIST +VALUES +EARLIEST +EARLIEST_TIME +LATEST +LATEST_TIME +PER_DAY +PER_HOUR +PER_MINUTE +PER_SECOND +RATE +SPARKLINE +C +DC +ABS +CEIL +CEILING +CONV +CRC32 +E +EXP +FLOOR +LN +LOG +LOG10 +LOG2 +MOD +PI +POW +POWER +RAND +ROUND +SIGN +SQRT +TRUNCATE +ACOS +ASIN +ATAN +ATAN2 +COS +COT +DEGREES +RADIANS +SIN +TAN +ADDDATE +DATE +DATE_ADD +DATE_SUB +DAYOFMONTH +DAYOFWEEK +DAYOFYEAR +DAYNAME +FROM_DAYS +MONTHNAME +SUBDATE +TIME +TIME_TO_SEC +TIMESTAMP +DATE_FORMAT +TO_DAYS +SUBSTR +SUBSTRING +LTRIM +RTRIM +TRIM +TO +LOWER +UPPER +CONCAT +CONCAT_WS +LENGTH +STRCMP +RIGHT +LEFT +ASCII +LOCATE +REPLACE +CAST +LIKE +ISNULL +ISNOTNULL +IFNULL +NULLIF +IF +MATCH +MATCH_PHRASE +SIMPLE_QUERY_STRING +ALLOW_LEADING_WILDCARD +ANALYZE_WILDCARD +ANALYZER +AUTO_GENERATE_SYNONYMS_PHRASE_QUERY +BOOST +CUTOFF_FREQUENCY +DEFAULT_FIELD +DEFAULT_OPERATOR +ENABLE_POSITION_INCREMENTS +FLAGS +FUZZY_MAX_EXPANSIONS +FUZZY_PREFIX_LENGTH +FUZZY_TRANSPOSITIONS +FUZZY_REWRITE +FUZZINESS +LENIENT +LOW_FREQ_OPERATOR +MAX_DETERMINIZED_STATES +MAX_EXPANSIONS +MINIMUM_SHOULD_MATCH +OPERATOR +PHRASE_SLOP +PREFIX_LENGTH +QUOTE_ANALYZER +QUOTE_FIELD_SUFFIX +REWRITE +SLOP +TIE_BREAKER +TYPE +ZERO_TERMS_QUERY +SPAN +MS +S +M +H +W +Q +Y +ID +INTEGER_LITERAL +DECIMAL_LITERAL +ID_DATE_SUFFIX +DQUOTA_STRING +SQUOTA_STRING +BQUOTA_STRING +ERROR_RECOGNITION + +rule names: +SEARCH +FROM +WHERE +FIELDS +RENAME +STATS +DEDUP +SORT +EVAL +HEAD +TOP +RARE +PARSE +KMEANS +AD +AS +BY +SOURCE +INDEX +D +DESC +SORTBY +AUTO +STR +IP +NUM +KEEPEMPTY +CONSECUTIVE +DEDUP_SPLITVALUES +PARTITIONS +ALLNUM +DELIM +CENTROIDS +ITERATIONS +DISTANCE_TYPE +NUMBER_OF_TREES +SHINGLE_SIZE +SAMPLE_SIZE +OUTPUT_AFTER +TIME_DECAY +ANOMALY_RATE +TIME_FIELD +TIME_ZONE +TRAINING_DATA_SIZE +ANOMALY_SCORE_THRESHOLD +CASE +IN +NOT +OR +AND +XOR +TRUE +FALSE +REGEXP +DATETIME +INTERVAL +MICROSECOND +MILLISECOND +SECOND +MINUTE +HOUR +DAY +WEEK +MONTH +QUARTER +YEAR +SECOND_MICROSECOND +MINUTE_MICROSECOND +MINUTE_SECOND +HOUR_MICROSECOND +HOUR_SECOND +HOUR_MINUTE +DAY_MICROSECOND +DAY_SECOND +DAY_MINUTE +DAY_HOUR +YEAR_MONTH +DATAMODEL +LOOKUP +SAVEDSEARCH +INT +INTEGER +DOUBLE +LONG +FLOAT +STRING +BOOLEAN +PIPE +COMMA +DOT +EQUAL +GREATER +LESS +NOT_GREATER +NOT_LESS +NOT_EQUAL +PLUS +MINUS +STAR +DIVIDE +MODULE +EXCLAMATION_SYMBOL +COLON +LT_PRTHS +RT_PRTHS +LT_SQR_PRTHS +RT_SQR_PRTHS +SINGLE_QUOTE +DOUBLE_QUOTE +BACKTICK +BIT_NOT_OP +BIT_AND_OP +BIT_XOR_OP +AVG +COUNT +DISTINCT_COUNT +ESTDC +ESTDC_ERROR +MAX +MEAN +MEDIAN +MIN +MODE +RANGE +STDEV +STDEVP +SUM +SUMSQ +VAR_SAMP +VAR_POP +STDDEV_SAMP +STDDEV_POP +PERCENTILE +FIRST +LAST +LIST +VALUES +EARLIEST +EARLIEST_TIME +LATEST +LATEST_TIME +PER_DAY +PER_HOUR +PER_MINUTE +PER_SECOND +RATE +SPARKLINE +C +DC +ABS +CEIL +CEILING +CONV +CRC32 +E +EXP +FLOOR +LN +LOG +LOG10 +LOG2 +MOD +PI +POW +POWER +RAND +ROUND +SIGN +SQRT +TRUNCATE +ACOS +ASIN +ATAN +ATAN2 +COS +COT +DEGREES +RADIANS +SIN +TAN +ADDDATE +DATE +DATE_ADD +DATE_SUB +DAYOFMONTH +DAYOFWEEK +DAYOFYEAR +DAYNAME +FROM_DAYS +MONTHNAME +SUBDATE +TIME +TIME_TO_SEC +TIMESTAMP +DATE_FORMAT +TO_DAYS +SUBSTR +SUBSTRING +LTRIM +RTRIM +TRIM +TO +LOWER +UPPER +CONCAT +CONCAT_WS +LENGTH +STRCMP +RIGHT +LEFT +ASCII +LOCATE +REPLACE +CAST +LIKE +ISNULL +ISNOTNULL +IFNULL +NULLIF +IF +MATCH +MATCH_PHRASE +SIMPLE_QUERY_STRING +ALLOW_LEADING_WILDCARD +ANALYZE_WILDCARD +ANALYZER +AUTO_GENERATE_SYNONYMS_PHRASE_QUERY +BOOST +CUTOFF_FREQUENCY +DEFAULT_FIELD +DEFAULT_OPERATOR +ENABLE_POSITION_INCREMENTS +FLAGS +FUZZY_MAX_EXPANSIONS +FUZZY_PREFIX_LENGTH +FUZZY_TRANSPOSITIONS +FUZZY_REWRITE +FUZZINESS +LENIENT +LOW_FREQ_OPERATOR +MAX_DETERMINIZED_STATES +MAX_EXPANSIONS +MINIMUM_SHOULD_MATCH +OPERATOR +PHRASE_SLOP +PREFIX_LENGTH +QUOTE_ANALYZER +QUOTE_FIELD_SUFFIX +REWRITE +SLOP +TIE_BREAKER +TYPE +ZERO_TERMS_QUERY +SPAN +MS +S +M +H +W +Q +Y +ID +INTEGER_LITERAL +DECIMAL_LITERAL +DATE_SUFFIX +ID_LITERAL +ID_DATE_SUFFIX +DQUOTA_STRING +SQUOTA_STRING +BQUOTA_STRING +DEC_DIGIT +ERROR_RECOGNITION + +channel names: +DEFAULT_TOKEN_CHANNEL +HIDDEN +null +null +WHITESPACE +ERRORCHANNEL + +mode names: +DEFAULT_MODE + +atn: +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 271, 2671, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9, 49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54, 4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4, 60, 9, 60, 4, 61, 9, 61, 4, 62, 9, 62, 4, 63, 9, 63, 4, 64, 9, 64, 4, 65, 9, 65, 4, 66, 9, 66, 4, 67, 9, 67, 4, 68, 9, 68, 4, 69, 9, 69, 4, 70, 9, 70, 4, 71, 9, 71, 4, 72, 9, 72, 4, 73, 9, 73, 4, 74, 9, 74, 4, 75, 9, 75, 4, 76, 9, 76, 4, 77, 9, 77, 4, 78, 9, 78, 4, 79, 9, 79, 4, 80, 9, 80, 4, 81, 9, 81, 4, 82, 9, 82, 4, 83, 9, 83, 4, 84, 9, 84, 4, 85, 9, 85, 4, 86, 9, 86, 4, 87, 9, 87, 4, 88, 9, 88, 4, 89, 9, 89, 4, 90, 9, 90, 4, 91, 9, 91, 4, 92, 9, 92, 4, 93, 9, 93, 4, 94, 9, 94, 4, 95, 9, 95, 4, 96, 9, 96, 4, 97, 9, 97, 4, 98, 9, 98, 4, 99, 9, 99, 4, 100, 9, 100, 4, 101, 9, 101, 4, 102, 9, 102, 4, 103, 9, 103, 4, 104, 9, 104, 4, 105, 9, 105, 4, 106, 9, 106, 4, 107, 9, 107, 4, 108, 9, 108, 4, 109, 9, 109, 4, 110, 9, 110, 4, 111, 9, 111, 4, 112, 9, 112, 4, 113, 9, 113, 4, 114, 9, 114, 4, 115, 9, 115, 4, 116, 9, 116, 4, 117, 9, 117, 4, 118, 9, 118, 4, 119, 9, 119, 4, 120, 9, 120, 4, 121, 9, 121, 4, 122, 9, 122, 4, 123, 9, 123, 4, 124, 9, 124, 4, 125, 9, 125, 4, 126, 9, 126, 4, 127, 9, 127, 4, 128, 9, 128, 4, 129, 9, 129, 4, 130, 9, 130, 4, 131, 9, 131, 4, 132, 9, 132, 4, 133, 9, 133, 4, 134, 9, 134, 4, 135, 9, 135, 4, 136, 9, 136, 4, 137, 9, 137, 4, 138, 9, 138, 4, 139, 9, 139, 4, 140, 9, 140, 4, 141, 9, 141, 4, 142, 9, 142, 4, 143, 9, 143, 4, 144, 9, 144, 4, 145, 9, 145, 4, 146, 9, 146, 4, 147, 9, 147, 4, 148, 9, 148, 4, 149, 9, 149, 4, 150, 9, 150, 4, 151, 9, 151, 4, 152, 9, 152, 4, 153, 9, 153, 4, 154, 9, 154, 4, 155, 9, 155, 4, 156, 9, 156, 4, 157, 9, 157, 4, 158, 9, 158, 4, 159, 9, 159, 4, 160, 9, 160, 4, 161, 9, 161, 4, 162, 9, 162, 4, 163, 9, 163, 4, 164, 9, 164, 4, 165, 9, 165, 4, 166, 9, 166, 4, 167, 9, 167, 4, 168, 9, 168, 4, 169, 9, 169, 4, 170, 9, 170, 4, 171, 9, 171, 4, 172, 9, 172, 4, 173, 9, 173, 4, 174, 9, 174, 4, 175, 9, 175, 4, 176, 9, 176, 4, 177, 9, 177, 4, 178, 9, 178, 4, 179, 9, 179, 4, 180, 9, 180, 4, 181, 9, 181, 4, 182, 9, 182, 4, 183, 9, 183, 4, 184, 9, 184, 4, 185, 9, 185, 4, 186, 9, 186, 4, 187, 9, 187, 4, 188, 9, 188, 4, 189, 9, 189, 4, 190, 9, 190, 4, 191, 9, 191, 4, 192, 9, 192, 4, 193, 9, 193, 4, 194, 9, 194, 4, 195, 9, 195, 4, 196, 9, 196, 4, 197, 9, 197, 4, 198, 9, 198, 4, 199, 9, 199, 4, 200, 9, 200, 4, 201, 9, 201, 4, 202, 9, 202, 4, 203, 9, 203, 4, 204, 9, 204, 4, 205, 9, 205, 4, 206, 9, 206, 4, 207, 9, 207, 4, 208, 9, 208, 4, 209, 9, 209, 4, 210, 9, 210, 4, 211, 9, 211, 4, 212, 9, 212, 4, 213, 9, 213, 4, 214, 9, 214, 4, 215, 9, 215, 4, 216, 9, 216, 4, 217, 9, 217, 4, 218, 9, 218, 4, 219, 9, 219, 4, 220, 9, 220, 4, 221, 9, 221, 4, 222, 9, 222, 4, 223, 9, 223, 4, 224, 9, 224, 4, 225, 9, 225, 4, 226, 9, 226, 4, 227, 9, 227, 4, 228, 9, 228, 4, 229, 9, 229, 4, 230, 9, 230, 4, 231, 9, 231, 4, 232, 9, 232, 4, 233, 9, 233, 4, 234, 9, 234, 4, 235, 9, 235, 4, 236, 9, 236, 4, 237, 9, 237, 4, 238, 9, 238, 4, 239, 9, 239, 4, 240, 9, 240, 4, 241, 9, 241, 4, 242, 9, 242, 4, 243, 9, 243, 4, 244, 9, 244, 4, 245, 9, 245, 4, 246, 9, 246, 4, 247, 9, 247, 4, 248, 9, 248, 4, 249, 9, 249, 4, 250, 9, 250, 4, 251, 9, 251, 4, 252, 9, 252, 4, 253, 9, 253, 4, 254, 9, 254, 4, 255, 9, 255, 4, 256, 9, 256, 4, 257, 9, 257, 4, 258, 9, 258, 4, 259, 9, 259, 4, 260, 9, 260, 4, 261, 9, 261, 4, 262, 9, 262, 4, 263, 9, 263, 4, 264, 9, 264, 4, 265, 9, 265, 4, 266, 9, 266, 4, 267, 9, 267, 4, 268, 9, 268, 4, 269, 9, 269, 4, 270, 9, 270, 4, 271, 9, 271, 4, 272, 9, 272, 4, 273, 9, 273, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 3, 35, 3, 35, 3, 35, 3, 35, 3, 35, 3, 35, 3, 35, 3, 35, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 38, 3, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3, 41, 3, 41, 3, 41, 3, 41, 3, 41, 3, 41, 3, 41, 3, 41, 3, 41, 3, 41, 3, 41, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 45, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 46, 3, 47, 3, 47, 3, 47, 3, 47, 3, 47, 3, 48, 3, 48, 3, 48, 3, 49, 3, 49, 3, 49, 3, 49, 3, 50, 3, 50, 3, 50, 3, 51, 3, 51, 3, 51, 3, 51, 3, 52, 3, 52, 3, 52, 3, 52, 3, 53, 3, 53, 3, 53, 3, 53, 3, 53, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 54, 3, 55, 3, 55, 3, 55, 3, 55, 3, 55, 3, 55, 3, 55, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 56, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 57, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 58, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 59, 3, 60, 3, 60, 3, 60, 3, 60, 3, 60, 3, 60, 3, 60, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 62, 3, 62, 3, 62, 3, 62, 3, 62, 3, 63, 3, 63, 3, 63, 3, 63, 3, 64, 3, 64, 3, 64, 3, 64, 3, 64, 3, 65, 3, 65, 3, 65, 3, 65, 3, 65, 3, 65, 3, 66, 3, 66, 3, 66, 3, 66, 3, 66, 3, 66, 3, 66, 3, 66, 3, 67, 3, 67, 3, 67, 3, 67, 3, 67, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 68, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 69, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 70, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 71, 3, 72, 3, 72, 3, 72, 3, 72, 3, 72, 3, 72, 3, 72, 3, 72, 3, 72, 3, 72, 3, 72, 3, 72, 3, 73, 3, 73, 3, 73, 3, 73, 3, 73, 3, 73, 3, 73, 3, 73, 3, 73, 3, 73, 3, 73, 3, 73, 3, 74, 3, 74, 3, 74, 3, 74, 3, 74, 3, 74, 3, 74, 3, 74, 3, 74, 3, 74, 3, 74, 3, 74, 3, 74, 3, 74, 3, 74, 3, 74, 3, 75, 3, 75, 3, 75, 3, 75, 3, 75, 3, 75, 3, 75, 3, 75, 3, 75, 3, 75, 3, 75, 3, 76, 3, 76, 3, 76, 3, 76, 3, 76, 3, 76, 3, 76, 3, 76, 3, 76, 3, 76, 3, 76, 3, 77, 3, 77, 3, 77, 3, 77, 3, 77, 3, 77, 3, 77, 3, 77, 3, 77, 3, 78, 3, 78, 3, 78, 3, 78, 3, 78, 3, 78, 3, 78, 3, 78, 3, 78, 3, 78, 3, 78, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 79, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 80, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 81, 3, 82, 3, 82, 3, 82, 3, 82, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 83, 3, 84, 3, 84, 3, 84, 3, 84, 3, 84, 3, 84, 3, 84, 3, 85, 3, 85, 3, 85, 3, 85, 3, 85, 3, 86, 3, 86, 3, 86, 3, 86, 3, 86, 3, 86, 3, 87, 3, 87, 3, 87, 3, 87, 3, 87, 3, 87, 3, 87, 3, 88, 3, 88, 3, 88, 3, 88, 3, 88, 3, 88, 3, 88, 3, 88, 3, 89, 3, 89, 3, 90, 3, 90, 3, 91, 3, 91, 3, 92, 3, 92, 3, 93, 3, 93, 3, 94, 3, 94, 3, 95, 3, 95, 3, 95, 3, 96, 3, 96, 3, 96, 3, 97, 3, 97, 3, 97, 3, 98, 3, 98, 3, 99, 3, 99, 3, 100, 3, 100, 3, 101, 3, 101, 3, 102, 3, 102, 3, 103, 3, 103, 3, 104, 3, 104, 3, 105, 3, 105, 3, 106, 3, 106, 3, 107, 3, 107, 3, 108, 3, 108, 3, 109, 3, 109, 3, 110, 3, 110, 3, 111, 3, 111, 3, 112, 3, 112, 3, 113, 3, 113, 3, 114, 3, 114, 3, 115, 3, 115, 3, 115, 3, 115, 3, 116, 3, 116, 3, 116, 3, 116, 3, 116, 3, 116, 3, 117, 3, 117, 3, 117, 3, 117, 3, 117, 3, 117, 3, 117, 3, 117, 3, 117, 3, 117, 3, 117, 3, 117, 3, 117, 3, 117, 3, 117, 3, 118, 3, 118, 3, 118, 3, 118, 3, 118, 3, 118, 3, 119, 3, 119, 3, 119, 3, 119, 3, 119, 3, 119, 3, 119, 3, 119, 3, 119, 3, 119, 3, 119, 3, 119, 3, 120, 3, 120, 3, 120, 3, 120, 3, 121, 3, 121, 3, 121, 3, 121, 3, 121, 3, 122, 3, 122, 3, 122, 3, 122, 3, 122, 3, 122, 3, 122, 3, 123, 3, 123, 3, 123, 3, 123, 3, 124, 3, 124, 3, 124, 3, 124, 3, 124, 3, 125, 3, 125, 3, 125, 3, 125, 3, 125, 3, 125, 3, 126, 3, 126, 3, 126, 3, 126, 3, 126, 3, 126, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 127, 3, 128, 3, 128, 3, 128, 3, 128, 3, 129, 3, 129, 3, 129, 3, 129, 3, 129, 3, 129, 3, 130, 3, 130, 3, 130, 3, 130, 3, 130, 3, 130, 3, 130, 3, 130, 3, 130, 3, 131, 3, 131, 3, 131, 3, 131, 3, 131, 3, 131, 3, 131, 3, 131, 3, 132, 3, 132, 3, 132, 3, 132, 3, 132, 3, 132, 3, 132, 3, 132, 3, 132, 3, 132, 3, 132, 3, 132, 3, 133, 3, 133, 3, 133, 3, 133, 3, 133, 3, 133, 3, 133, 3, 133, 3, 133, 3, 133, 3, 133, 3, 134, 3, 134, 3, 134, 3, 134, 3, 134, 3, 134, 3, 134, 3, 134, 3, 134, 3, 134, 3, 134, 3, 135, 3, 135, 3, 135, 3, 135, 3, 135, 3, 135, 3, 136, 3, 136, 3, 136, 3, 136, 3, 136, 3, 137, 3, 137, 3, 137, 3, 137, 3, 137, 3, 138, 3, 138, 3, 138, 3, 138, 3, 138, 3, 138, 3, 138, 3, 139, 3, 139, 3, 139, 3, 139, 3, 139, 3, 139, 3, 139, 3, 139, 3, 139, 3, 140, 3, 140, 3, 140, 3, 140, 3, 140, 3, 140, 3, 140, 3, 140, 3, 140, 3, 140, 3, 140, 3, 140, 3, 140, 3, 140, 3, 141, 3, 141, 3, 141, 3, 141, 3, 141, 3, 141, 3, 141, 3, 142, 3, 142, 3, 142, 3, 142, 3, 142, 3, 142, 3, 142, 3, 142, 3, 142, 3, 142, 3, 142, 3, 142, 3, 143, 3, 143, 3, 143, 3, 143, 3, 143, 3, 143, 3, 143, 3, 143, 3, 144, 3, 144, 3, 144, 3, 144, 3, 144, 3, 144, 3, 144, 3, 144, 3, 144, 3, 145, 3, 145, 3, 145, 3, 145, 3, 145, 3, 145, 3, 145, 3, 145, 3, 145, 3, 145, 3, 145, 3, 146, 3, 146, 3, 146, 3, 146, 3, 146, 3, 146, 3, 146, 3, 146, 3, 146, 3, 146, 3, 146, 3, 147, 3, 147, 3, 147, 3, 147, 3, 147, 3, 148, 3, 148, 3, 148, 3, 148, 3, 148, 3, 148, 3, 148, 3, 148, 3, 148, 3, 148, 3, 149, 3, 149, 3, 150, 3, 150, 3, 150, 3, 151, 3, 151, 3, 151, 3, 151, 3, 152, 3, 152, 3, 152, 3, 152, 3, 152, 3, 153, 3, 153, 3, 153, 3, 153, 3, 153, 3, 153, 3, 153, 3, 153, 3, 154, 3, 154, 3, 154, 3, 154, 3, 154, 3, 155, 3, 155, 3, 155, 3, 155, 3, 155, 3, 155, 3, 156, 3, 156, 3, 157, 3, 157, 3, 157, 3, 157, 3, 158, 3, 158, 3, 158, 3, 158, 3, 158, 3, 158, 3, 159, 3, 159, 3, 159, 3, 160, 3, 160, 3, 160, 3, 160, 3, 161, 3, 161, 3, 161, 3, 161, 3, 161, 3, 161, 3, 162, 3, 162, 3, 162, 3, 162, 3, 162, 3, 163, 3, 163, 3, 163, 3, 163, 3, 164, 3, 164, 3, 164, 3, 165, 3, 165, 3, 165, 3, 165, 3, 166, 3, 166, 3, 166, 3, 166, 3, 166, 3, 166, 3, 167, 3, 167, 3, 167, 3, 167, 3, 167, 3, 168, 3, 168, 3, 168, 3, 168, 3, 168, 3, 168, 3, 169, 3, 169, 3, 169, 3, 169, 3, 169, 3, 170, 3, 170, 3, 170, 3, 170, 3, 170, 3, 171, 3, 171, 3, 171, 3, 171, 3, 171, 3, 171, 3, 171, 3, 171, 3, 171, 3, 172, 3, 172, 3, 172, 3, 172, 3, 172, 3, 173, 3, 173, 3, 173, 3, 173, 3, 173, 3, 174, 3, 174, 3, 174, 3, 174, 3, 174, 3, 175, 3, 175, 3, 175, 3, 175, 3, 175, 3, 175, 3, 176, 3, 176, 3, 176, 3, 176, 3, 177, 3, 177, 3, 177, 3, 177, 3, 178, 3, 178, 3, 178, 3, 178, 3, 178, 3, 178, 3, 178, 3, 178, 3, 179, 3, 179, 3, 179, 3, 179, 3, 179, 3, 179, 3, 179, 3, 179, 3, 180, 3, 180, 3, 180, 3, 180, 3, 181, 3, 181, 3, 181, 3, 181, 3, 182, 3, 182, 3, 182, 3, 182, 3, 182, 3, 182, 3, 182, 3, 182, 3, 183, 3, 183, 3, 183, 3, 183, 3, 183, 3, 184, 3, 184, 3, 184, 3, 184, 3, 184, 3, 184, 3, 184, 3, 184, 3, 184, 3, 185, 3, 185, 3, 185, 3, 185, 3, 185, 3, 185, 3, 185, 3, 185, 3, 185, 3, 186, 3, 186, 3, 186, 3, 186, 3, 186, 3, 186, 3, 186, 3, 186, 3, 186, 3, 186, 3, 186, 3, 187, 3, 187, 3, 187, 3, 187, 3, 187, 3, 187, 3, 187, 3, 187, 3, 187, 3, 187, 3, 188, 3, 188, 3, 188, 3, 188, 3, 188, 3, 188, 3, 188, 3, 188, 3, 188, 3, 188, 3, 189, 3, 189, 3, 189, 3, 189, 3, 189, 3, 189, 3, 189, 3, 189, 3, 190, 3, 190, 3, 190, 3, 190, 3, 190, 3, 190, 3, 190, 3, 190, 3, 190, 3, 190, 3, 191, 3, 191, 3, 191, 3, 191, 3, 191, 3, 191, 3, 191, 3, 191, 3, 191, 3, 191, 3, 192, 3, 192, 3, 192, 3, 192, 3, 192, 3, 192, 3, 192, 3, 192, 3, 193, 3, 193, 3, 193, 3, 193, 3, 193, 3, 194, 3, 194, 3, 194, 3, 194, 3, 194, 3, 194, 3, 194, 3, 194, 3, 194, 3, 194, 3, 194, 3, 194, 3, 195, 3, 195, 3, 195, 3, 195, 3, 195, 3, 195, 3, 195, 3, 195, 3, 195, 3, 195, 3, 196, 3, 196, 3, 196, 3, 196, 3, 196, 3, 196, 3, 196, 3, 196, 3, 196, 3, 196, 3, 196, 3, 196, 3, 197, 3, 197, 3, 197, 3, 197, 3, 197, 3, 197, 3, 197, 3, 197, 3, 198, 3, 198, 3, 198, 3, 198, 3, 198, 3, 198, 3, 198, 3, 199, 3, 199, 3, 199, 3, 199, 3, 199, 3, 199, 3, 199, 3, 199, 3, 199, 3, 199, 3, 200, 3, 200, 3, 200, 3, 200, 3, 200, 3, 200, 3, 201, 3, 201, 3, 201, 3, 201, 3, 201, 3, 201, 3, 202, 3, 202, 3, 202, 3, 202, 3, 202, 3, 203, 3, 203, 3, 203, 3, 204, 3, 204, 3, 204, 3, 204, 3, 204, 3, 204, 3, 205, 3, 205, 3, 205, 3, 205, 3, 205, 3, 205, 3, 206, 3, 206, 3, 206, 3, 206, 3, 206, 3, 206, 3, 206, 3, 207, 3, 207, 3, 207, 3, 207, 3, 207, 3, 207, 3, 207, 3, 207, 3, 207, 3, 207, 3, 208, 3, 208, 3, 208, 3, 208, 3, 208, 3, 208, 3, 208, 3, 209, 3, 209, 3, 209, 3, 209, 3, 209, 3, 209, 3, 209, 3, 210, 3, 210, 3, 210, 3, 210, 3, 210, 3, 210, 3, 211, 3, 211, 3, 211, 3, 211, 3, 211, 3, 212, 3, 212, 3, 212, 3, 212, 3, 212, 3, 212, 3, 213, 3, 213, 3, 213, 3, 213, 3, 213, 3, 213, 3, 213, 3, 214, 3, 214, 3, 214, 3, 214, 3, 214, 3, 214, 3, 214, 3, 214, 3, 215, 3, 215, 3, 215, 3, 215, 3, 215, 3, 216, 3, 216, 3, 216, 3, 216, 3, 216, 3, 217, 3, 217, 3, 217, 3, 217, 3, 217, 3, 217, 3, 217, 3, 218, 3, 218, 3, 218, 3, 218, 3, 218, 3, 218, 3, 218, 3, 218, 3, 218, 3, 218, 3, 219, 3, 219, 3, 219, 3, 219, 3, 219, 3, 219, 3, 219, 3, 220, 3, 220, 3, 220, 3, 220, 3, 220, 3, 220, 3, 220, 3, 221, 3, 221, 3, 221, 3, 222, 3, 222, 3, 222, 3, 222, 3, 222, 3, 222, 3, 223, 3, 223, 3, 223, 3, 223, 3, 223, 3, 223, 3, 223, 3, 223, 3, 223, 3, 223, 3, 223, 3, 223, 3, 223, 3, 224, 3, 224, 3, 224, 3, 224, 3, 224, 3, 224, 3, 224, 3, 224, 3, 224, 3, 224, 3, 224, 3, 224, 3, 224, 3, 224, 3, 224, 3, 224, 3, 224, 3, 224, 3, 224, 3, 224, 3, 225, 3, 225, 3, 225, 3, 225, 3, 225, 3, 225, 3, 225, 3, 225, 3, 225, 3, 225, 3, 225, 3, 225, 3, 225, 3, 225, 3, 225, 3, 225, 3, 225, 3, 225, 3, 225, 3, 225, 3, 225, 3, 225, 3, 225, 3, 226, 3, 226, 3, 226, 3, 226, 3, 226, 3, 226, 3, 226, 3, 226, 3, 226, 3, 226, 3, 226, 3, 226, 3, 226, 3, 226, 3, 226, 3, 226, 3, 226, 3, 227, 3, 227, 3, 227, 3, 227, 3, 227, 3, 227, 3, 227, 3, 227, 3, 227, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 228, 3, 229, 3, 229, 3, 229, 3, 229, 3, 229, 3, 229, 3, 230, 3, 230, 3, 230, 3, 230, 3, 230, 3, 230, 3, 230, 3, 230, 3, 230, 3, 230, 3, 230, 3, 230, 3, 230, 3, 230, 3, 230, 3, 230, 3, 230, 3, 231, 3, 231, 3, 231, 3, 231, 3, 231, 3, 231, 3, 231, 3, 231, 3, 231, 3, 231, 3, 231, 3, 231, 3, 231, 3, 231, 3, 232, 3, 232, 3, 232, 3, 232, 3, 232, 3, 232, 3, 232, 3, 232, 3, 232, 3, 232, 3, 232, 3, 232, 3, 232, 3, 232, 3, 232, 3, 232, 3, 232, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 233, 3, 234, 3, 234, 3, 234, 3, 234, 3, 234, 3, 234, 3, 235, 3, 235, 3, 235, 3, 235, 3, 235, 3, 235, 3, 235, 3, 235, 3, 235, 3, 235, 3, 235, 3, 235, 3, 235, 3, 235, 3, 235, 3, 235, 3, 235, 3, 235, 3, 235, 3, 235, 3, 235, 3, 236, 3, 236, 3, 236, 3, 236, 3, 236, 3, 236, 3, 236, 3, 236, 3, 236, 3, 236, 3, 236, 3, 236, 3, 236, 3, 236, 3, 236, 3, 236, 3, 236, 3, 236, 3, 236, 3, 236, 3, 237, 3, 237, 3, 237, 3, 237, 3, 237, 3, 237, 3, 237, 3, 237, 3, 237, 3, 237, 3, 237, 3, 237, 3, 237, 3, 237, 3, 237, 3, 237, 3, 237, 3, 237, 3, 237, 3, 237, 3, 237, 3, 238, 3, 238, 3, 238, 3, 238, 3, 238, 3, 238, 3, 238, 3, 238, 3, 238, 3, 238, 3, 238, 3, 238, 3, 238, 3, 238, 3, 239, 3, 239, 3, 239, 3, 239, 3, 239, 3, 239, 3, 239, 3, 239, 3, 239, 3, 239, 3, 240, 3, 240, 3, 240, 3, 240, 3, 240, 3, 240, 3, 240, 3, 240, 3, 241, 3, 241, 3, 241, 3, 241, 3, 241, 3, 241, 3, 241, 3, 241, 3, 241, 3, 241, 3, 241, 3, 241, 3, 241, 3, 241, 3, 241, 3, 241, 3, 241, 3, 241, 3, 242, 3, 242, 3, 242, 3, 242, 3, 242, 3, 242, 3, 242, 3, 242, 3, 242, 3, 242, 3, 242, 3, 242, 3, 242, 3, 242, 3, 242, 3, 242, 3, 242, 3, 242, 3, 242, 3, 242, 3, 242, 3, 242, 3, 242, 3, 242, 3, 243, 3, 243, 3, 243, 3, 243, 3, 243, 3, 243, 3, 243, 3, 243, 3, 243, 3, 243, 3, 243, 3, 243, 3, 243, 3, 243, 3, 243, 3, 244, 3, 244, 3, 244, 3, 244, 3, 244, 3, 244, 3, 244, 3, 244, 3, 244, 3, 244, 3, 244, 3, 244, 3, 244, 3, 244, 3, 244, 3, 244, 3, 244, 3, 244, 3, 244, 3, 244, 3, 244, 3, 245, 3, 245, 3, 245, 3, 245, 3, 245, 3, 245, 3, 245, 3, 245, 3, 245, 3, 246, 3, 246, 3, 246, 3, 246, 3, 246, 3, 246, 3, 246, 3, 246, 3, 246, 3, 246, 3, 246, 3, 246, 3, 247, 3, 247, 3, 247, 3, 247, 3, 247, 3, 247, 3, 247, 3, 247, 3, 247, 3, 247, 3, 247, 3, 247, 3, 247, 3, 247, 3, 248, 3, 248, 3, 248, 3, 248, 3, 248, 3, 248, 3, 248, 3, 248, 3, 248, 3, 248, 3, 248, 3, 248, 3, 248, 3, 248, 3, 248, 3, 249, 3, 249, 3, 249, 3, 249, 3, 249, 3, 249, 3, 249, 3, 249, 3, 249, 3, 249, 3, 249, 3, 249, 3, 249, 3, 249, 3, 249, 3, 249, 3, 249, 3, 249, 3, 249, 3, 250, 3, 250, 3, 250, 3, 250, 3, 250, 3, 250, 3, 250, 3, 250, 3, 251, 3, 251, 3, 251, 3, 251, 3, 251, 3, 252, 3, 252, 3, 252, 3, 252, 3, 252, 3, 252, 3, 252, 3, 252, 3, 252, 3, 252, 3, 252, 3, 252, 3, 253, 3, 253, 3, 253, 3, 253, 3, 253, 3, 254, 3, 254, 3, 254, 3, 254, 3, 254, 3, 254, 3, 254, 3, 254, 3, 254, 3, 254, 3, 254, 3, 254, 3, 254, 3, 254, 3, 254, 3, 254, 3, 254, 3, 255, 3, 255, 3, 255, 3, 255, 3, 255, 3, 256, 3, 256, 3, 256, 3, 257, 3, 257, 3, 258, 3, 258, 3, 259, 3, 259, 3, 260, 3, 260, 3, 261, 3, 261, 3, 262, 3, 262, 3, 263, 3, 263, 3, 264, 6, 264, 2585, 10, 264, 13, 264, 14, 264, 2586, 3, 265, 6, 265, 2590, 10, 265, 13, 265, 14, 265, 2591, 5, 265, 2594, 10, 265, 3, 265, 3, 265, 6, 265, 2598, 10, 265, 13, 265, 14, 265, 2599, 3, 266, 3, 266, 6, 266, 2604, 10, 266, 13, 266, 14, 266, 2605, 7, 266, 2608, 10, 266, 12, 266, 14, 266, 2611, 11, 266, 3, 267, 6, 267, 2614, 10, 267, 13, 267, 14, 267, 2615, 3, 267, 7, 267, 2619, 10, 267, 12, 267, 14, 267, 2622, 11, 267, 3, 268, 3, 268, 3, 268, 3, 269, 3, 269, 3, 269, 3, 269, 3, 269, 3, 269, 7, 269, 2633, 10, 269, 12, 269, 14, 269, 2636, 11, 269, 3, 269, 3, 269, 3, 270, 3, 270, 3, 270, 3, 270, 3, 270, 3, 270, 7, 270, 2646, 10, 270, 12, 270, 14, 270, 2649, 11, 270, 3, 270, 3, 270, 3, 271, 3, 271, 3, 271, 3, 271, 3, 271, 3, 271, 7, 271, 2659, 10, 271, 12, 271, 14, 271, 2662, 11, 271, 3, 271, 3, 271, 3, 272, 3, 272, 3, 273, 3, 273, 3, 273, 3, 273, 3, 2615, 2, 274, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 20, 39, 21, 41, 22, 43, 23, 45, 24, 47, 25, 49, 26, 51, 27, 53, 28, 55, 29, 57, 30, 59, 31, 61, 32, 63, 33, 65, 34, 67, 35, 69, 36, 71, 37, 73, 38, 75, 39, 77, 40, 79, 41, 81, 42, 83, 43, 85, 44, 87, 45, 89, 46, 91, 47, 93, 48, 95, 49, 97, 50, 99, 51, 101, 52, 103, 53, 105, 54, 107, 55, 109, 56, 111, 57, 113, 58, 115, 59, 117, 60, 119, 61, 121, 62, 123, 63, 125, 64, 127, 65, 129, 66, 131, 67, 133, 68, 135, 69, 137, 70, 139, 71, 141, 72, 143, 73, 145, 74, 147, 75, 149, 76, 151, 77, 153, 78, 155, 79, 157, 80, 159, 81, 161, 82, 163, 83, 165, 84, 167, 85, 169, 86, 171, 87, 173, 88, 175, 89, 177, 90, 179, 91, 181, 92, 183, 93, 185, 94, 187, 95, 189, 96, 191, 97, 193, 98, 195, 99, 197, 100, 199, 101, 201, 102, 203, 103, 205, 104, 207, 105, 209, 106, 211, 107, 213, 108, 215, 109, 217, 110, 219, 111, 221, 112, 223, 113, 225, 114, 227, 115, 229, 116, 231, 117, 233, 118, 235, 119, 237, 120, 239, 121, 241, 122, 243, 123, 245, 124, 247, 125, 249, 126, 251, 127, 253, 128, 255, 129, 257, 130, 259, 131, 261, 132, 263, 133, 265, 134, 267, 135, 269, 136, 271, 137, 273, 138, 275, 139, 277, 140, 279, 141, 281, 142, 283, 143, 285, 144, 287, 145, 289, 146, 291, 147, 293, 148, 295, 149, 297, 150, 299, 151, 301, 152, 303, 153, 305, 154, 307, 155, 309, 156, 311, 157, 313, 158, 315, 159, 317, 160, 319, 161, 321, 162, 323, 163, 325, 164, 327, 165, 329, 166, 331, 167, 333, 168, 335, 169, 337, 170, 339, 171, 341, 172, 343, 173, 345, 174, 347, 175, 349, 176, 351, 177, 353, 178, 355, 179, 357, 180, 359, 181, 361, 182, 363, 183, 365, 184, 367, 185, 369, 186, 371, 187, 373, 188, 375, 189, 377, 190, 379, 191, 381, 192, 383, 193, 385, 194, 387, 195, 389, 196, 391, 197, 393, 198, 395, 199, 397, 200, 399, 201, 401, 202, 403, 203, 405, 204, 407, 205, 409, 206, 411, 207, 413, 208, 415, 209, 417, 210, 419, 211, 421, 212, 423, 213, 425, 214, 427, 215, 429, 216, 431, 217, 433, 218, 435, 219, 437, 220, 439, 221, 441, 222, 443, 223, 445, 224, 447, 225, 449, 226, 451, 227, 453, 228, 455, 229, 457, 230, 459, 231, 461, 232, 463, 233, 465, 234, 467, 235, 469, 236, 471, 237, 473, 238, 475, 239, 477, 240, 479, 241, 481, 242, 483, 243, 485, 244, 487, 245, 489, 246, 491, 247, 493, 248, 495, 249, 497, 250, 499, 251, 501, 252, 503, 253, 505, 254, 507, 255, 509, 256, 511, 257, 513, 258, 515, 259, 517, 260, 519, 261, 521, 262, 523, 263, 525, 264, 527, 265, 529, 266, 531, 2, 533, 2, 535, 267, 537, 268, 539, 269, 541, 270, 543, 2, 545, 271, 3, 2, 10, 3, 2, 47, 48, 4, 2, 44, 44, 50, 59, 4, 2, 44, 44, 66, 92, 7, 2, 44, 44, 47, 47, 50, 59, 67, 92, 97, 97, 4, 2, 36, 36, 94, 94, 4, 2, 41, 41, 94, 94, 4, 2, 94, 94, 98, 98, 3, 2, 50, 59, 2, 2684, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, 2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 2, 79, 3, 2, 2, 2, 2, 81, 3, 2, 2, 2, 2, 83, 3, 2, 2, 2, 2, 85, 3, 2, 2, 2, 2, 87, 3, 2, 2, 2, 2, 89, 3, 2, 2, 2, 2, 91, 3, 2, 2, 2, 2, 93, 3, 2, 2, 2, 2, 95, 3, 2, 2, 2, 2, 97, 3, 2, 2, 2, 2, 99, 3, 2, 2, 2, 2, 101, 3, 2, 2, 2, 2, 103, 3, 2, 2, 2, 2, 105, 3, 2, 2, 2, 2, 107, 3, 2, 2, 2, 2, 109, 3, 2, 2, 2, 2, 111, 3, 2, 2, 2, 2, 113, 3, 2, 2, 2, 2, 115, 3, 2, 2, 2, 2, 117, 3, 2, 2, 2, 2, 119, 3, 2, 2, 2, 2, 121, 3, 2, 2, 2, 2, 123, 3, 2, 2, 2, 2, 125, 3, 2, 2, 2, 2, 127, 3, 2, 2, 2, 2, 129, 3, 2, 2, 2, 2, 131, 3, 2, 2, 2, 2, 133, 3, 2, 2, 2, 2, 135, 3, 2, 2, 2, 2, 137, 3, 2, 2, 2, 2, 139, 3, 2, 2, 2, 2, 141, 3, 2, 2, 2, 2, 143, 3, 2, 2, 2, 2, 145, 3, 2, 2, 2, 2, 147, 3, 2, 2, 2, 2, 149, 3, 2, 2, 2, 2, 151, 3, 2, 2, 2, 2, 153, 3, 2, 2, 2, 2, 155, 3, 2, 2, 2, 2, 157, 3, 2, 2, 2, 2, 159, 3, 2, 2, 2, 2, 161, 3, 2, 2, 2, 2, 163, 3, 2, 2, 2, 2, 165, 3, 2, 2, 2, 2, 167, 3, 2, 2, 2, 2, 169, 3, 2, 2, 2, 2, 171, 3, 2, 2, 2, 2, 173, 3, 2, 2, 2, 2, 175, 3, 2, 2, 2, 2, 177, 3, 2, 2, 2, 2, 179, 3, 2, 2, 2, 2, 181, 3, 2, 2, 2, 2, 183, 3, 2, 2, 2, 2, 185, 3, 2, 2, 2, 2, 187, 3, 2, 2, 2, 2, 189, 3, 2, 2, 2, 2, 191, 3, 2, 2, 2, 2, 193, 3, 2, 2, 2, 2, 195, 3, 2, 2, 2, 2, 197, 3, 2, 2, 2, 2, 199, 3, 2, 2, 2, 2, 201, 3, 2, 2, 2, 2, 203, 3, 2, 2, 2, 2, 205, 3, 2, 2, 2, 2, 207, 3, 2, 2, 2, 2, 209, 3, 2, 2, 2, 2, 211, 3, 2, 2, 2, 2, 213, 3, 2, 2, 2, 2, 215, 3, 2, 2, 2, 2, 217, 3, 2, 2, 2, 2, 219, 3, 2, 2, 2, 2, 221, 3, 2, 2, 2, 2, 223, 3, 2, 2, 2, 2, 225, 3, 2, 2, 2, 2, 227, 3, 2, 2, 2, 2, 229, 3, 2, 2, 2, 2, 231, 3, 2, 2, 2, 2, 233, 3, 2, 2, 2, 2, 235, 3, 2, 2, 2, 2, 237, 3, 2, 2, 2, 2, 239, 3, 2, 2, 2, 2, 241, 3, 2, 2, 2, 2, 243, 3, 2, 2, 2, 2, 245, 3, 2, 2, 2, 2, 247, 3, 2, 2, 2, 2, 249, 3, 2, 2, 2, 2, 251, 3, 2, 2, 2, 2, 253, 3, 2, 2, 2, 2, 255, 3, 2, 2, 2, 2, 257, 3, 2, 2, 2, 2, 259, 3, 2, 2, 2, 2, 261, 3, 2, 2, 2, 2, 263, 3, 2, 2, 2, 2, 265, 3, 2, 2, 2, 2, 267, 3, 2, 2, 2, 2, 269, 3, 2, 2, 2, 2, 271, 3, 2, 2, 2, 2, 273, 3, 2, 2, 2, 2, 275, 3, 2, 2, 2, 2, 277, 3, 2, 2, 2, 2, 279, 3, 2, 2, 2, 2, 281, 3, 2, 2, 2, 2, 283, 3, 2, 2, 2, 2, 285, 3, 2, 2, 2, 2, 287, 3, 2, 2, 2, 2, 289, 3, 2, 2, 2, 2, 291, 3, 2, 2, 2, 2, 293, 3, 2, 2, 2, 2, 295, 3, 2, 2, 2, 2, 297, 3, 2, 2, 2, 2, 299, 3, 2, 2, 2, 2, 301, 3, 2, 2, 2, 2, 303, 3, 2, 2, 2, 2, 305, 3, 2, 2, 2, 2, 307, 3, 2, 2, 2, 2, 309, 3, 2, 2, 2, 2, 311, 3, 2, 2, 2, 2, 313, 3, 2, 2, 2, 2, 315, 3, 2, 2, 2, 2, 317, 3, 2, 2, 2, 2, 319, 3, 2, 2, 2, 2, 321, 3, 2, 2, 2, 2, 323, 3, 2, 2, 2, 2, 325, 3, 2, 2, 2, 2, 327, 3, 2, 2, 2, 2, 329, 3, 2, 2, 2, 2, 331, 3, 2, 2, 2, 2, 333, 3, 2, 2, 2, 2, 335, 3, 2, 2, 2, 2, 337, 3, 2, 2, 2, 2, 339, 3, 2, 2, 2, 2, 341, 3, 2, 2, 2, 2, 343, 3, 2, 2, 2, 2, 345, 3, 2, 2, 2, 2, 347, 3, 2, 2, 2, 2, 349, 3, 2, 2, 2, 2, 351, 3, 2, 2, 2, 2, 353, 3, 2, 2, 2, 2, 355, 3, 2, 2, 2, 2, 357, 3, 2, 2, 2, 2, 359, 3, 2, 2, 2, 2, 361, 3, 2, 2, 2, 2, 363, 3, 2, 2, 2, 2, 365, 3, 2, 2, 2, 2, 367, 3, 2, 2, 2, 2, 369, 3, 2, 2, 2, 2, 371, 3, 2, 2, 2, 2, 373, 3, 2, 2, 2, 2, 375, 3, 2, 2, 2, 2, 377, 3, 2, 2, 2, 2, 379, 3, 2, 2, 2, 2, 381, 3, 2, 2, 2, 2, 383, 3, 2, 2, 2, 2, 385, 3, 2, 2, 2, 2, 387, 3, 2, 2, 2, 2, 389, 3, 2, 2, 2, 2, 391, 3, 2, 2, 2, 2, 393, 3, 2, 2, 2, 2, 395, 3, 2, 2, 2, 2, 397, 3, 2, 2, 2, 2, 399, 3, 2, 2, 2, 2, 401, 3, 2, 2, 2, 2, 403, 3, 2, 2, 2, 2, 405, 3, 2, 2, 2, 2, 407, 3, 2, 2, 2, 2, 409, 3, 2, 2, 2, 2, 411, 3, 2, 2, 2, 2, 413, 3, 2, 2, 2, 2, 415, 3, 2, 2, 2, 2, 417, 3, 2, 2, 2, 2, 419, 3, 2, 2, 2, 2, 421, 3, 2, 2, 2, 2, 423, 3, 2, 2, 2, 2, 425, 3, 2, 2, 2, 2, 427, 3, 2, 2, 2, 2, 429, 3, 2, 2, 2, 2, 431, 3, 2, 2, 2, 2, 433, 3, 2, 2, 2, 2, 435, 3, 2, 2, 2, 2, 437, 3, 2, 2, 2, 2, 439, 3, 2, 2, 2, 2, 441, 3, 2, 2, 2, 2, 443, 3, 2, 2, 2, 2, 445, 3, 2, 2, 2, 2, 447, 3, 2, 2, 2, 2, 449, 3, 2, 2, 2, 2, 451, 3, 2, 2, 2, 2, 453, 3, 2, 2, 2, 2, 455, 3, 2, 2, 2, 2, 457, 3, 2, 2, 2, 2, 459, 3, 2, 2, 2, 2, 461, 3, 2, 2, 2, 2, 463, 3, 2, 2, 2, 2, 465, 3, 2, 2, 2, 2, 467, 3, 2, 2, 2, 2, 469, 3, 2, 2, 2, 2, 471, 3, 2, 2, 2, 2, 473, 3, 2, 2, 2, 2, 475, 3, 2, 2, 2, 2, 477, 3, 2, 2, 2, 2, 479, 3, 2, 2, 2, 2, 481, 3, 2, 2, 2, 2, 483, 3, 2, 2, 2, 2, 485, 3, 2, 2, 2, 2, 487, 3, 2, 2, 2, 2, 489, 3, 2, 2, 2, 2, 491, 3, 2, 2, 2, 2, 493, 3, 2, 2, 2, 2, 495, 3, 2, 2, 2, 2, 497, 3, 2, 2, 2, 2, 499, 3, 2, 2, 2, 2, 501, 3, 2, 2, 2, 2, 503, 3, 2, 2, 2, 2, 505, 3, 2, 2, 2, 2, 507, 3, 2, 2, 2, 2, 509, 3, 2, 2, 2, 2, 511, 3, 2, 2, 2, 2, 513, 3, 2, 2, 2, 2, 515, 3, 2, 2, 2, 2, 517, 3, 2, 2, 2, 2, 519, 3, 2, 2, 2, 2, 521, 3, 2, 2, 2, 2, 523, 3, 2, 2, 2, 2, 525, 3, 2, 2, 2, 2, 527, 3, 2, 2, 2, 2, 529, 3, 2, 2, 2, 2, 535, 3, 2, 2, 2, 2, 537, 3, 2, 2, 2, 2, 539, 3, 2, 2, 2, 2, 541, 3, 2, 2, 2, 2, 545, 3, 2, 2, 2, 3, 547, 3, 2, 2, 2, 5, 554, 3, 2, 2, 2, 7, 559, 3, 2, 2, 2, 9, 565, 3, 2, 2, 2, 11, 572, 3, 2, 2, 2, 13, 579, 3, 2, 2, 2, 15, 585, 3, 2, 2, 2, 17, 591, 3, 2, 2, 2, 19, 596, 3, 2, 2, 2, 21, 601, 3, 2, 2, 2, 23, 606, 3, 2, 2, 2, 25, 610, 3, 2, 2, 2, 27, 615, 3, 2, 2, 2, 29, 621, 3, 2, 2, 2, 31, 628, 3, 2, 2, 2, 33, 631, 3, 2, 2, 2, 35, 634, 3, 2, 2, 2, 37, 637, 3, 2, 2, 2, 39, 644, 3, 2, 2, 2, 41, 650, 3, 2, 2, 2, 43, 652, 3, 2, 2, 2, 45, 657, 3, 2, 2, 2, 47, 664, 3, 2, 2, 2, 49, 669, 3, 2, 2, 2, 51, 673, 3, 2, 2, 2, 53, 676, 3, 2, 2, 2, 55, 680, 3, 2, 2, 2, 57, 690, 3, 2, 2, 2, 59, 702, 3, 2, 2, 2, 61, 720, 3, 2, 2, 2, 63, 731, 3, 2, 2, 2, 65, 738, 3, 2, 2, 2, 67, 744, 3, 2, 2, 2, 69, 754, 3, 2, 2, 2, 71, 765, 3, 2, 2, 2, 73, 779, 3, 2, 2, 2, 75, 795, 3, 2, 2, 2, 77, 808, 3, 2, 2, 2, 79, 820, 3, 2, 2, 2, 81, 833, 3, 2, 2, 2, 83, 844, 3, 2, 2, 2, 85, 857, 3, 2, 2, 2, 87, 868, 3, 2, 2, 2, 89, 878, 3, 2, 2, 2, 91, 897, 3, 2, 2, 2, 93, 921, 3, 2, 2, 2, 95, 926, 3, 2, 2, 2, 97, 929, 3, 2, 2, 2, 99, 933, 3, 2, 2, 2, 101, 936, 3, 2, 2, 2, 103, 940, 3, 2, 2, 2, 105, 944, 3, 2, 2, 2, 107, 949, 3, 2, 2, 2, 109, 955, 3, 2, 2, 2, 111, 962, 3, 2, 2, 2, 113, 971, 3, 2, 2, 2, 115, 980, 3, 2, 2, 2, 117, 992, 3, 2, 2, 2, 119, 1004, 3, 2, 2, 2, 121, 1011, 3, 2, 2, 2, 123, 1018, 3, 2, 2, 2, 125, 1023, 3, 2, 2, 2, 127, 1027, 3, 2, 2, 2, 129, 1032, 3, 2, 2, 2, 131, 1038, 3, 2, 2, 2, 133, 1046, 3, 2, 2, 2, 135, 1051, 3, 2, 2, 2, 137, 1070, 3, 2, 2, 2, 139, 1089, 3, 2, 2, 2, 141, 1103, 3, 2, 2, 2, 143, 1120, 3, 2, 2, 2, 145, 1132, 3, 2, 2, 2, 147, 1144, 3, 2, 2, 2, 149, 1160, 3, 2, 2, 2, 151, 1171, 3, 2, 2, 2, 153, 1182, 3, 2, 2, 2, 155, 1191, 3, 2, 2, 2, 157, 1202, 3, 2, 2, 2, 159, 1212, 3, 2, 2, 2, 161, 1219, 3, 2, 2, 2, 163, 1231, 3, 2, 2, 2, 165, 1235, 3, 2, 2, 2, 167, 1243, 3, 2, 2, 2, 169, 1250, 3, 2, 2, 2, 171, 1255, 3, 2, 2, 2, 173, 1261, 3, 2, 2, 2, 175, 1268, 3, 2, 2, 2, 177, 1276, 3, 2, 2, 2, 179, 1278, 3, 2, 2, 2, 181, 1280, 3, 2, 2, 2, 183, 1282, 3, 2, 2, 2, 185, 1284, 3, 2, 2, 2, 187, 1286, 3, 2, 2, 2, 189, 1288, 3, 2, 2, 2, 191, 1291, 3, 2, 2, 2, 193, 1294, 3, 2, 2, 2, 195, 1297, 3, 2, 2, 2, 197, 1299, 3, 2, 2, 2, 199, 1301, 3, 2, 2, 2, 201, 1303, 3, 2, 2, 2, 203, 1305, 3, 2, 2, 2, 205, 1307, 3, 2, 2, 2, 207, 1309, 3, 2, 2, 2, 209, 1311, 3, 2, 2, 2, 211, 1313, 3, 2, 2, 2, 213, 1315, 3, 2, 2, 2, 215, 1317, 3, 2, 2, 2, 217, 1319, 3, 2, 2, 2, 219, 1321, 3, 2, 2, 2, 221, 1323, 3, 2, 2, 2, 223, 1325, 3, 2, 2, 2, 225, 1327, 3, 2, 2, 2, 227, 1329, 3, 2, 2, 2, 229, 1331, 3, 2, 2, 2, 231, 1335, 3, 2, 2, 2, 233, 1341, 3, 2, 2, 2, 235, 1356, 3, 2, 2, 2, 237, 1362, 3, 2, 2, 2, 239, 1374, 3, 2, 2, 2, 241, 1378, 3, 2, 2, 2, 243, 1383, 3, 2, 2, 2, 245, 1390, 3, 2, 2, 2, 247, 1394, 3, 2, 2, 2, 249, 1399, 3, 2, 2, 2, 251, 1405, 3, 2, 2, 2, 253, 1411, 3, 2, 2, 2, 255, 1418, 3, 2, 2, 2, 257, 1422, 3, 2, 2, 2, 259, 1428, 3, 2, 2, 2, 261, 1437, 3, 2, 2, 2, 263, 1445, 3, 2, 2, 2, 265, 1457, 3, 2, 2, 2, 267, 1468, 3, 2, 2, 2, 269, 1479, 3, 2, 2, 2, 271, 1485, 3, 2, 2, 2, 273, 1490, 3, 2, 2, 2, 275, 1495, 3, 2, 2, 2, 277, 1502, 3, 2, 2, 2, 279, 1511, 3, 2, 2, 2, 281, 1525, 3, 2, 2, 2, 283, 1532, 3, 2, 2, 2, 285, 1544, 3, 2, 2, 2, 287, 1552, 3, 2, 2, 2, 289, 1561, 3, 2, 2, 2, 291, 1572, 3, 2, 2, 2, 293, 1583, 3, 2, 2, 2, 295, 1588, 3, 2, 2, 2, 297, 1598, 3, 2, 2, 2, 299, 1600, 3, 2, 2, 2, 301, 1603, 3, 2, 2, 2, 303, 1607, 3, 2, 2, 2, 305, 1612, 3, 2, 2, 2, 307, 1620, 3, 2, 2, 2, 309, 1625, 3, 2, 2, 2, 311, 1631, 3, 2, 2, 2, 313, 1633, 3, 2, 2, 2, 315, 1637, 3, 2, 2, 2, 317, 1643, 3, 2, 2, 2, 319, 1646, 3, 2, 2, 2, 321, 1650, 3, 2, 2, 2, 323, 1656, 3, 2, 2, 2, 325, 1661, 3, 2, 2, 2, 327, 1665, 3, 2, 2, 2, 329, 1668, 3, 2, 2, 2, 331, 1672, 3, 2, 2, 2, 333, 1678, 3, 2, 2, 2, 335, 1683, 3, 2, 2, 2, 337, 1689, 3, 2, 2, 2, 339, 1694, 3, 2, 2, 2, 341, 1699, 3, 2, 2, 2, 343, 1708, 3, 2, 2, 2, 345, 1713, 3, 2, 2, 2, 347, 1718, 3, 2, 2, 2, 349, 1723, 3, 2, 2, 2, 351, 1729, 3, 2, 2, 2, 353, 1733, 3, 2, 2, 2, 355, 1737, 3, 2, 2, 2, 357, 1745, 3, 2, 2, 2, 359, 1753, 3, 2, 2, 2, 361, 1757, 3, 2, 2, 2, 363, 1761, 3, 2, 2, 2, 365, 1769, 3, 2, 2, 2, 367, 1774, 3, 2, 2, 2, 369, 1783, 3, 2, 2, 2, 371, 1792, 3, 2, 2, 2, 373, 1803, 3, 2, 2, 2, 375, 1813, 3, 2, 2, 2, 377, 1823, 3, 2, 2, 2, 379, 1831, 3, 2, 2, 2, 381, 1841, 3, 2, 2, 2, 383, 1851, 3, 2, 2, 2, 385, 1859, 3, 2, 2, 2, 387, 1864, 3, 2, 2, 2, 389, 1876, 3, 2, 2, 2, 391, 1886, 3, 2, 2, 2, 393, 1898, 3, 2, 2, 2, 395, 1906, 3, 2, 2, 2, 397, 1913, 3, 2, 2, 2, 399, 1923, 3, 2, 2, 2, 401, 1929, 3, 2, 2, 2, 403, 1935, 3, 2, 2, 2, 405, 1940, 3, 2, 2, 2, 407, 1943, 3, 2, 2, 2, 409, 1949, 3, 2, 2, 2, 411, 1955, 3, 2, 2, 2, 413, 1962, 3, 2, 2, 2, 415, 1972, 3, 2, 2, 2, 417, 1979, 3, 2, 2, 2, 419, 1986, 3, 2, 2, 2, 421, 1992, 3, 2, 2, 2, 423, 1997, 3, 2, 2, 2, 425, 2003, 3, 2, 2, 2, 427, 2010, 3, 2, 2, 2, 429, 2018, 3, 2, 2, 2, 431, 2023, 3, 2, 2, 2, 433, 2028, 3, 2, 2, 2, 435, 2035, 3, 2, 2, 2, 437, 2045, 3, 2, 2, 2, 439, 2052, 3, 2, 2, 2, 441, 2059, 3, 2, 2, 2, 443, 2062, 3, 2, 2, 2, 445, 2068, 3, 2, 2, 2, 447, 2081, 3, 2, 2, 2, 449, 2101, 3, 2, 2, 2, 451, 2124, 3, 2, 2, 2, 453, 2141, 3, 2, 2, 2, 455, 2150, 3, 2, 2, 2, 457, 2186, 3, 2, 2, 2, 459, 2192, 3, 2, 2, 2, 461, 2209, 3, 2, 2, 2, 463, 2223, 3, 2, 2, 2, 465, 2240, 3, 2, 2, 2, 467, 2267, 3, 2, 2, 2, 469, 2273, 3, 2, 2, 2, 471, 2294, 3, 2, 2, 2, 473, 2314, 3, 2, 2, 2, 475, 2335, 3, 2, 2, 2, 477, 2349, 3, 2, 2, 2, 479, 2359, 3, 2, 2, 2, 481, 2367, 3, 2, 2, 2, 483, 2385, 3, 2, 2, 2, 485, 2409, 3, 2, 2, 2, 487, 2424, 3, 2, 2, 2, 489, 2445, 3, 2, 2, 2, 491, 2454, 3, 2, 2, 2, 493, 2466, 3, 2, 2, 2, 495, 2480, 3, 2, 2, 2, 497, 2495, 3, 2, 2, 2, 499, 2514, 3, 2, 2, 2, 501, 2522, 3, 2, 2, 2, 503, 2527, 3, 2, 2, 2, 505, 2539, 3, 2, 2, 2, 507, 2544, 3, 2, 2, 2, 509, 2561, 3, 2, 2, 2, 511, 2566, 3, 2, 2, 2, 513, 2569, 3, 2, 2, 2, 515, 2571, 3, 2, 2, 2, 517, 2573, 3, 2, 2, 2, 519, 2575, 3, 2, 2, 2, 521, 2577, 3, 2, 2, 2, 523, 2579, 3, 2, 2, 2, 525, 2581, 3, 2, 2, 2, 527, 2584, 3, 2, 2, 2, 529, 2593, 3, 2, 2, 2, 531, 2609, 3, 2, 2, 2, 533, 2613, 3, 2, 2, 2, 535, 2623, 3, 2, 2, 2, 537, 2626, 3, 2, 2, 2, 539, 2639, 3, 2, 2, 2, 541, 2652, 3, 2, 2, 2, 543, 2665, 3, 2, 2, 2, 545, 2667, 3, 2, 2, 2, 547, 548, 7, 85, 2, 2, 548, 549, 7, 71, 2, 2, 549, 550, 7, 67, 2, 2, 550, 551, 7, 84, 2, 2, 551, 552, 7, 69, 2, 2, 552, 553, 7, 74, 2, 2, 553, 4, 3, 2, 2, 2, 554, 555, 7, 72, 2, 2, 555, 556, 7, 84, 2, 2, 556, 557, 7, 81, 2, 2, 557, 558, 7, 79, 2, 2, 558, 6, 3, 2, 2, 2, 559, 560, 7, 89, 2, 2, 560, 561, 7, 74, 2, 2, 561, 562, 7, 71, 2, 2, 562, 563, 7, 84, 2, 2, 563, 564, 7, 71, 2, 2, 564, 8, 3, 2, 2, 2, 565, 566, 7, 72, 2, 2, 566, 567, 7, 75, 2, 2, 567, 568, 7, 71, 2, 2, 568, 569, 7, 78, 2, 2, 569, 570, 7, 70, 2, 2, 570, 571, 7, 85, 2, 2, 571, 10, 3, 2, 2, 2, 572, 573, 7, 84, 2, 2, 573, 574, 7, 71, 2, 2, 574, 575, 7, 80, 2, 2, 575, 576, 7, 67, 2, 2, 576, 577, 7, 79, 2, 2, 577, 578, 7, 71, 2, 2, 578, 12, 3, 2, 2, 2, 579, 580, 7, 85, 2, 2, 580, 581, 7, 86, 2, 2, 581, 582, 7, 67, 2, 2, 582, 583, 7, 86, 2, 2, 583, 584, 7, 85, 2, 2, 584, 14, 3, 2, 2, 2, 585, 586, 7, 70, 2, 2, 586, 587, 7, 71, 2, 2, 587, 588, 7, 70, 2, 2, 588, 589, 7, 87, 2, 2, 589, 590, 7, 82, 2, 2, 590, 16, 3, 2, 2, 2, 591, 592, 7, 85, 2, 2, 592, 593, 7, 81, 2, 2, 593, 594, 7, 84, 2, 2, 594, 595, 7, 86, 2, 2, 595, 18, 3, 2, 2, 2, 596, 597, 7, 71, 2, 2, 597, 598, 7, 88, 2, 2, 598, 599, 7, 67, 2, 2, 599, 600, 7, 78, 2, 2, 600, 20, 3, 2, 2, 2, 601, 602, 7, 74, 2, 2, 602, 603, 7, 71, 2, 2, 603, 604, 7, 67, 2, 2, 604, 605, 7, 70, 2, 2, 605, 22, 3, 2, 2, 2, 606, 607, 7, 86, 2, 2, 607, 608, 7, 81, 2, 2, 608, 609, 7, 82, 2, 2, 609, 24, 3, 2, 2, 2, 610, 611, 7, 84, 2, 2, 611, 612, 7, 67, 2, 2, 612, 613, 7, 84, 2, 2, 613, 614, 7, 71, 2, 2, 614, 26, 3, 2, 2, 2, 615, 616, 7, 82, 2, 2, 616, 617, 7, 67, 2, 2, 617, 618, 7, 84, 2, 2, 618, 619, 7, 85, 2, 2, 619, 620, 7, 71, 2, 2, 620, 28, 3, 2, 2, 2, 621, 622, 7, 77, 2, 2, 622, 623, 7, 79, 2, 2, 623, 624, 7, 71, 2, 2, 624, 625, 7, 67, 2, 2, 625, 626, 7, 80, 2, 2, 626, 627, 7, 85, 2, 2, 627, 30, 3, 2, 2, 2, 628, 629, 7, 67, 2, 2, 629, 630, 7, 70, 2, 2, 630, 32, 3, 2, 2, 2, 631, 632, 7, 67, 2, 2, 632, 633, 7, 85, 2, 2, 633, 34, 3, 2, 2, 2, 634, 635, 7, 68, 2, 2, 635, 636, 7, 91, 2, 2, 636, 36, 3, 2, 2, 2, 637, 638, 7, 85, 2, 2, 638, 639, 7, 81, 2, 2, 639, 640, 7, 87, 2, 2, 640, 641, 7, 84, 2, 2, 641, 642, 7, 69, 2, 2, 642, 643, 7, 71, 2, 2, 643, 38, 3, 2, 2, 2, 644, 645, 7, 75, 2, 2, 645, 646, 7, 80, 2, 2, 646, 647, 7, 70, 2, 2, 647, 648, 7, 71, 2, 2, 648, 649, 7, 90, 2, 2, 649, 40, 3, 2, 2, 2, 650, 651, 7, 70, 2, 2, 651, 42, 3, 2, 2, 2, 652, 653, 7, 70, 2, 2, 653, 654, 7, 71, 2, 2, 654, 655, 7, 85, 2, 2, 655, 656, 7, 69, 2, 2, 656, 44, 3, 2, 2, 2, 657, 658, 7, 85, 2, 2, 658, 659, 7, 81, 2, 2, 659, 660, 7, 84, 2, 2, 660, 661, 7, 86, 2, 2, 661, 662, 7, 68, 2, 2, 662, 663, 7, 91, 2, 2, 663, 46, 3, 2, 2, 2, 664, 665, 7, 67, 2, 2, 665, 666, 7, 87, 2, 2, 666, 667, 7, 86, 2, 2, 667, 668, 7, 81, 2, 2, 668, 48, 3, 2, 2, 2, 669, 670, 7, 85, 2, 2, 670, 671, 7, 86, 2, 2, 671, 672, 7, 84, 2, 2, 672, 50, 3, 2, 2, 2, 673, 674, 7, 75, 2, 2, 674, 675, 7, 82, 2, 2, 675, 52, 3, 2, 2, 2, 676, 677, 7, 80, 2, 2, 677, 678, 7, 87, 2, 2, 678, 679, 7, 79, 2, 2, 679, 54, 3, 2, 2, 2, 680, 681, 7, 77, 2, 2, 681, 682, 7, 71, 2, 2, 682, 683, 7, 71, 2, 2, 683, 684, 7, 82, 2, 2, 684, 685, 7, 71, 2, 2, 685, 686, 7, 79, 2, 2, 686, 687, 7, 82, 2, 2, 687, 688, 7, 86, 2, 2, 688, 689, 7, 91, 2, 2, 689, 56, 3, 2, 2, 2, 690, 691, 7, 69, 2, 2, 691, 692, 7, 81, 2, 2, 692, 693, 7, 80, 2, 2, 693, 694, 7, 85, 2, 2, 694, 695, 7, 71, 2, 2, 695, 696, 7, 69, 2, 2, 696, 697, 7, 87, 2, 2, 697, 698, 7, 86, 2, 2, 698, 699, 7, 75, 2, 2, 699, 700, 7, 88, 2, 2, 700, 701, 7, 71, 2, 2, 701, 58, 3, 2, 2, 2, 702, 703, 7, 70, 2, 2, 703, 704, 7, 71, 2, 2, 704, 705, 7, 70, 2, 2, 705, 706, 7, 87, 2, 2, 706, 707, 7, 82, 2, 2, 707, 708, 7, 97, 2, 2, 708, 709, 7, 85, 2, 2, 709, 710, 7, 82, 2, 2, 710, 711, 7, 78, 2, 2, 711, 712, 7, 75, 2, 2, 712, 713, 7, 86, 2, 2, 713, 714, 7, 88, 2, 2, 714, 715, 7, 67, 2, 2, 715, 716, 7, 78, 2, 2, 716, 717, 7, 87, 2, 2, 717, 718, 7, 71, 2, 2, 718, 719, 7, 85, 2, 2, 719, 60, 3, 2, 2, 2, 720, 721, 7, 82, 2, 2, 721, 722, 7, 67, 2, 2, 722, 723, 7, 84, 2, 2, 723, 724, 7, 86, 2, 2, 724, 725, 7, 75, 2, 2, 725, 726, 7, 86, 2, 2, 726, 727, 7, 75, 2, 2, 727, 728, 7, 81, 2, 2, 728, 729, 7, 80, 2, 2, 729, 730, 7, 85, 2, 2, 730, 62, 3, 2, 2, 2, 731, 732, 7, 67, 2, 2, 732, 733, 7, 78, 2, 2, 733, 734, 7, 78, 2, 2, 734, 735, 7, 80, 2, 2, 735, 736, 7, 87, 2, 2, 736, 737, 7, 79, 2, 2, 737, 64, 3, 2, 2, 2, 738, 739, 7, 70, 2, 2, 739, 740, 7, 71, 2, 2, 740, 741, 7, 78, 2, 2, 741, 742, 7, 75, 2, 2, 742, 743, 7, 79, 2, 2, 743, 66, 3, 2, 2, 2, 744, 745, 7, 69, 2, 2, 745, 746, 7, 71, 2, 2, 746, 747, 7, 80, 2, 2, 747, 748, 7, 86, 2, 2, 748, 749, 7, 84, 2, 2, 749, 750, 7, 81, 2, 2, 750, 751, 7, 75, 2, 2, 751, 752, 7, 70, 2, 2, 752, 753, 7, 85, 2, 2, 753, 68, 3, 2, 2, 2, 754, 755, 7, 75, 2, 2, 755, 756, 7, 86, 2, 2, 756, 757, 7, 71, 2, 2, 757, 758, 7, 84, 2, 2, 758, 759, 7, 67, 2, 2, 759, 760, 7, 86, 2, 2, 760, 761, 7, 75, 2, 2, 761, 762, 7, 81, 2, 2, 762, 763, 7, 80, 2, 2, 763, 764, 7, 85, 2, 2, 764, 70, 3, 2, 2, 2, 765, 766, 7, 70, 2, 2, 766, 767, 7, 75, 2, 2, 767, 768, 7, 85, 2, 2, 768, 769, 7, 86, 2, 2, 769, 770, 7, 67, 2, 2, 770, 771, 7, 80, 2, 2, 771, 772, 7, 69, 2, 2, 772, 773, 7, 71, 2, 2, 773, 774, 7, 97, 2, 2, 774, 775, 7, 86, 2, 2, 775, 776, 7, 91, 2, 2, 776, 777, 7, 82, 2, 2, 777, 778, 7, 71, 2, 2, 778, 72, 3, 2, 2, 2, 779, 780, 7, 80, 2, 2, 780, 781, 7, 87, 2, 2, 781, 782, 7, 79, 2, 2, 782, 783, 7, 68, 2, 2, 783, 784, 7, 71, 2, 2, 784, 785, 7, 84, 2, 2, 785, 786, 7, 97, 2, 2, 786, 787, 7, 81, 2, 2, 787, 788, 7, 72, 2, 2, 788, 789, 7, 97, 2, 2, 789, 790, 7, 86, 2, 2, 790, 791, 7, 84, 2, 2, 791, 792, 7, 71, 2, 2, 792, 793, 7, 71, 2, 2, 793, 794, 7, 85, 2, 2, 794, 74, 3, 2, 2, 2, 795, 796, 7, 85, 2, 2, 796, 797, 7, 74, 2, 2, 797, 798, 7, 75, 2, 2, 798, 799, 7, 80, 2, 2, 799, 800, 7, 73, 2, 2, 800, 801, 7, 78, 2, 2, 801, 802, 7, 71, 2, 2, 802, 803, 7, 97, 2, 2, 803, 804, 7, 85, 2, 2, 804, 805, 7, 75, 2, 2, 805, 806, 7, 92, 2, 2, 806, 807, 7, 71, 2, 2, 807, 76, 3, 2, 2, 2, 808, 809, 7, 85, 2, 2, 809, 810, 7, 67, 2, 2, 810, 811, 7, 79, 2, 2, 811, 812, 7, 82, 2, 2, 812, 813, 7, 78, 2, 2, 813, 814, 7, 71, 2, 2, 814, 815, 7, 97, 2, 2, 815, 816, 7, 85, 2, 2, 816, 817, 7, 75, 2, 2, 817, 818, 7, 92, 2, 2, 818, 819, 7, 71, 2, 2, 819, 78, 3, 2, 2, 2, 820, 821, 7, 81, 2, 2, 821, 822, 7, 87, 2, 2, 822, 823, 7, 86, 2, 2, 823, 824, 7, 82, 2, 2, 824, 825, 7, 87, 2, 2, 825, 826, 7, 86, 2, 2, 826, 827, 7, 97, 2, 2, 827, 828, 7, 67, 2, 2, 828, 829, 7, 72, 2, 2, 829, 830, 7, 86, 2, 2, 830, 831, 7, 71, 2, 2, 831, 832, 7, 84, 2, 2, 832, 80, 3, 2, 2, 2, 833, 834, 7, 86, 2, 2, 834, 835, 7, 75, 2, 2, 835, 836, 7, 79, 2, 2, 836, 837, 7, 71, 2, 2, 837, 838, 7, 97, 2, 2, 838, 839, 7, 70, 2, 2, 839, 840, 7, 71, 2, 2, 840, 841, 7, 69, 2, 2, 841, 842, 7, 67, 2, 2, 842, 843, 7, 91, 2, 2, 843, 82, 3, 2, 2, 2, 844, 845, 7, 67, 2, 2, 845, 846, 7, 80, 2, 2, 846, 847, 7, 81, 2, 2, 847, 848, 7, 79, 2, 2, 848, 849, 7, 67, 2, 2, 849, 850, 7, 78, 2, 2, 850, 851, 7, 91, 2, 2, 851, 852, 7, 97, 2, 2, 852, 853, 7, 84, 2, 2, 853, 854, 7, 67, 2, 2, 854, 855, 7, 86, 2, 2, 855, 856, 7, 71, 2, 2, 856, 84, 3, 2, 2, 2, 857, 858, 7, 86, 2, 2, 858, 859, 7, 75, 2, 2, 859, 860, 7, 79, 2, 2, 860, 861, 7, 71, 2, 2, 861, 862, 7, 97, 2, 2, 862, 863, 7, 72, 2, 2, 863, 864, 7, 75, 2, 2, 864, 865, 7, 71, 2, 2, 865, 866, 7, 78, 2, 2, 866, 867, 7, 70, 2, 2, 867, 86, 3, 2, 2, 2, 868, 869, 7, 86, 2, 2, 869, 870, 7, 75, 2, 2, 870, 871, 7, 79, 2, 2, 871, 872, 7, 71, 2, 2, 872, 873, 7, 97, 2, 2, 873, 874, 7, 92, 2, 2, 874, 875, 7, 81, 2, 2, 875, 876, 7, 80, 2, 2, 876, 877, 7, 71, 2, 2, 877, 88, 3, 2, 2, 2, 878, 879, 7, 86, 2, 2, 879, 880, 7, 84, 2, 2, 880, 881, 7, 67, 2, 2, 881, 882, 7, 75, 2, 2, 882, 883, 7, 80, 2, 2, 883, 884, 7, 75, 2, 2, 884, 885, 7, 80, 2, 2, 885, 886, 7, 73, 2, 2, 886, 887, 7, 97, 2, 2, 887, 888, 7, 70, 2, 2, 888, 889, 7, 67, 2, 2, 889, 890, 7, 86, 2, 2, 890, 891, 7, 67, 2, 2, 891, 892, 7, 97, 2, 2, 892, 893, 7, 85, 2, 2, 893, 894, 7, 75, 2, 2, 894, 895, 7, 92, 2, 2, 895, 896, 7, 71, 2, 2, 896, 90, 3, 2, 2, 2, 897, 898, 7, 67, 2, 2, 898, 899, 7, 80, 2, 2, 899, 900, 7, 81, 2, 2, 900, 901, 7, 79, 2, 2, 901, 902, 7, 67, 2, 2, 902, 903, 7, 78, 2, 2, 903, 904, 7, 91, 2, 2, 904, 905, 7, 97, 2, 2, 905, 906, 7, 85, 2, 2, 906, 907, 7, 69, 2, 2, 907, 908, 7, 81, 2, 2, 908, 909, 7, 84, 2, 2, 909, 910, 7, 71, 2, 2, 910, 911, 7, 97, 2, 2, 911, 912, 7, 86, 2, 2, 912, 913, 7, 74, 2, 2, 913, 914, 7, 84, 2, 2, 914, 915, 7, 71, 2, 2, 915, 916, 7, 85, 2, 2, 916, 917, 7, 74, 2, 2, 917, 918, 7, 81, 2, 2, 918, 919, 7, 78, 2, 2, 919, 920, 7, 70, 2, 2, 920, 92, 3, 2, 2, 2, 921, 922, 7, 69, 2, 2, 922, 923, 7, 67, 2, 2, 923, 924, 7, 85, 2, 2, 924, 925, 7, 71, 2, 2, 925, 94, 3, 2, 2, 2, 926, 927, 7, 75, 2, 2, 927, 928, 7, 80, 2, 2, 928, 96, 3, 2, 2, 2, 929, 930, 7, 80, 2, 2, 930, 931, 7, 81, 2, 2, 931, 932, 7, 86, 2, 2, 932, 98, 3, 2, 2, 2, 933, 934, 7, 81, 2, 2, 934, 935, 7, 84, 2, 2, 935, 100, 3, 2, 2, 2, 936, 937, 7, 67, 2, 2, 937, 938, 7, 80, 2, 2, 938, 939, 7, 70, 2, 2, 939, 102, 3, 2, 2, 2, 940, 941, 7, 90, 2, 2, 941, 942, 7, 81, 2, 2, 942, 943, 7, 84, 2, 2, 943, 104, 3, 2, 2, 2, 944, 945, 7, 86, 2, 2, 945, 946, 7, 84, 2, 2, 946, 947, 7, 87, 2, 2, 947, 948, 7, 71, 2, 2, 948, 106, 3, 2, 2, 2, 949, 950, 7, 72, 2, 2, 950, 951, 7, 67, 2, 2, 951, 952, 7, 78, 2, 2, 952, 953, 7, 85, 2, 2, 953, 954, 7, 71, 2, 2, 954, 108, 3, 2, 2, 2, 955, 956, 7, 84, 2, 2, 956, 957, 7, 71, 2, 2, 957, 958, 7, 73, 2, 2, 958, 959, 7, 71, 2, 2, 959, 960, 7, 90, 2, 2, 960, 961, 7, 82, 2, 2, 961, 110, 3, 2, 2, 2, 962, 963, 7, 70, 2, 2, 963, 964, 7, 67, 2, 2, 964, 965, 7, 86, 2, 2, 965, 966, 7, 71, 2, 2, 966, 967, 7, 86, 2, 2, 967, 968, 7, 75, 2, 2, 968, 969, 7, 79, 2, 2, 969, 970, 7, 71, 2, 2, 970, 112, 3, 2, 2, 2, 971, 972, 7, 75, 2, 2, 972, 973, 7, 80, 2, 2, 973, 974, 7, 86, 2, 2, 974, 975, 7, 71, 2, 2, 975, 976, 7, 84, 2, 2, 976, 977, 7, 88, 2, 2, 977, 978, 7, 67, 2, 2, 978, 979, 7, 78, 2, 2, 979, 114, 3, 2, 2, 2, 980, 981, 7, 79, 2, 2, 981, 982, 7, 75, 2, 2, 982, 983, 7, 69, 2, 2, 983, 984, 7, 84, 2, 2, 984, 985, 7, 81, 2, 2, 985, 986, 7, 85, 2, 2, 986, 987, 7, 71, 2, 2, 987, 988, 7, 69, 2, 2, 988, 989, 7, 81, 2, 2, 989, 990, 7, 80, 2, 2, 990, 991, 7, 70, 2, 2, 991, 116, 3, 2, 2, 2, 992, 993, 7, 79, 2, 2, 993, 994, 7, 75, 2, 2, 994, 995, 7, 78, 2, 2, 995, 996, 7, 78, 2, 2, 996, 997, 7, 75, 2, 2, 997, 998, 7, 85, 2, 2, 998, 999, 7, 71, 2, 2, 999, 1000, 7, 69, 2, 2, 1000, 1001, 7, 81, 2, 2, 1001, 1002, 7, 80, 2, 2, 1002, 1003, 7, 70, 2, 2, 1003, 118, 3, 2, 2, 2, 1004, 1005, 7, 85, 2, 2, 1005, 1006, 7, 71, 2, 2, 1006, 1007, 7, 69, 2, 2, 1007, 1008, 7, 81, 2, 2, 1008, 1009, 7, 80, 2, 2, 1009, 1010, 7, 70, 2, 2, 1010, 120, 3, 2, 2, 2, 1011, 1012, 7, 79, 2, 2, 1012, 1013, 7, 75, 2, 2, 1013, 1014, 7, 80, 2, 2, 1014, 1015, 7, 87, 2, 2, 1015, 1016, 7, 86, 2, 2, 1016, 1017, 7, 71, 2, 2, 1017, 122, 3, 2, 2, 2, 1018, 1019, 7, 74, 2, 2, 1019, 1020, 7, 81, 2, 2, 1020, 1021, 7, 87, 2, 2, 1021, 1022, 7, 84, 2, 2, 1022, 124, 3, 2, 2, 2, 1023, 1024, 7, 70, 2, 2, 1024, 1025, 7, 67, 2, 2, 1025, 1026, 7, 91, 2, 2, 1026, 126, 3, 2, 2, 2, 1027, 1028, 7, 89, 2, 2, 1028, 1029, 7, 71, 2, 2, 1029, 1030, 7, 71, 2, 2, 1030, 1031, 7, 77, 2, 2, 1031, 128, 3, 2, 2, 2, 1032, 1033, 7, 79, 2, 2, 1033, 1034, 7, 81, 2, 2, 1034, 1035, 7, 80, 2, 2, 1035, 1036, 7, 86, 2, 2, 1036, 1037, 7, 74, 2, 2, 1037, 130, 3, 2, 2, 2, 1038, 1039, 7, 83, 2, 2, 1039, 1040, 7, 87, 2, 2, 1040, 1041, 7, 67, 2, 2, 1041, 1042, 7, 84, 2, 2, 1042, 1043, 7, 86, 2, 2, 1043, 1044, 7, 71, 2, 2, 1044, 1045, 7, 84, 2, 2, 1045, 132, 3, 2, 2, 2, 1046, 1047, 7, 91, 2, 2, 1047, 1048, 7, 71, 2, 2, 1048, 1049, 7, 67, 2, 2, 1049, 1050, 7, 84, 2, 2, 1050, 134, 3, 2, 2, 2, 1051, 1052, 7, 85, 2, 2, 1052, 1053, 7, 71, 2, 2, 1053, 1054, 7, 69, 2, 2, 1054, 1055, 7, 81, 2, 2, 1055, 1056, 7, 80, 2, 2, 1056, 1057, 7, 70, 2, 2, 1057, 1058, 7, 97, 2, 2, 1058, 1059, 7, 79, 2, 2, 1059, 1060, 7, 75, 2, 2, 1060, 1061, 7, 69, 2, 2, 1061, 1062, 7, 84, 2, 2, 1062, 1063, 7, 81, 2, 2, 1063, 1064, 7, 85, 2, 2, 1064, 1065, 7, 71, 2, 2, 1065, 1066, 7, 69, 2, 2, 1066, 1067, 7, 81, 2, 2, 1067, 1068, 7, 80, 2, 2, 1068, 1069, 7, 70, 2, 2, 1069, 136, 3, 2, 2, 2, 1070, 1071, 7, 79, 2, 2, 1071, 1072, 7, 75, 2, 2, 1072, 1073, 7, 80, 2, 2, 1073, 1074, 7, 87, 2, 2, 1074, 1075, 7, 86, 2, 2, 1075, 1076, 7, 71, 2, 2, 1076, 1077, 7, 97, 2, 2, 1077, 1078, 7, 79, 2, 2, 1078, 1079, 7, 75, 2, 2, 1079, 1080, 7, 69, 2, 2, 1080, 1081, 7, 84, 2, 2, 1081, 1082, 7, 81, 2, 2, 1082, 1083, 7, 85, 2, 2, 1083, 1084, 7, 71, 2, 2, 1084, 1085, 7, 69, 2, 2, 1085, 1086, 7, 81, 2, 2, 1086, 1087, 7, 80, 2, 2, 1087, 1088, 7, 70, 2, 2, 1088, 138, 3, 2, 2, 2, 1089, 1090, 7, 79, 2, 2, 1090, 1091, 7, 75, 2, 2, 1091, 1092, 7, 80, 2, 2, 1092, 1093, 7, 87, 2, 2, 1093, 1094, 7, 86, 2, 2, 1094, 1095, 7, 71, 2, 2, 1095, 1096, 7, 97, 2, 2, 1096, 1097, 7, 85, 2, 2, 1097, 1098, 7, 71, 2, 2, 1098, 1099, 7, 69, 2, 2, 1099, 1100, 7, 81, 2, 2, 1100, 1101, 7, 80, 2, 2, 1101, 1102, 7, 70, 2, 2, 1102, 140, 3, 2, 2, 2, 1103, 1104, 7, 74, 2, 2, 1104, 1105, 7, 81, 2, 2, 1105, 1106, 7, 87, 2, 2, 1106, 1107, 7, 84, 2, 2, 1107, 1108, 7, 97, 2, 2, 1108, 1109, 7, 79, 2, 2, 1109, 1110, 7, 75, 2, 2, 1110, 1111, 7, 69, 2, 2, 1111, 1112, 7, 84, 2, 2, 1112, 1113, 7, 81, 2, 2, 1113, 1114, 7, 85, 2, 2, 1114, 1115, 7, 71, 2, 2, 1115, 1116, 7, 69, 2, 2, 1116, 1117, 7, 81, 2, 2, 1117, 1118, 7, 80, 2, 2, 1118, 1119, 7, 70, 2, 2, 1119, 142, 3, 2, 2, 2, 1120, 1121, 7, 74, 2, 2, 1121, 1122, 7, 81, 2, 2, 1122, 1123, 7, 87, 2, 2, 1123, 1124, 7, 84, 2, 2, 1124, 1125, 7, 97, 2, 2, 1125, 1126, 7, 85, 2, 2, 1126, 1127, 7, 71, 2, 2, 1127, 1128, 7, 69, 2, 2, 1128, 1129, 7, 81, 2, 2, 1129, 1130, 7, 80, 2, 2, 1130, 1131, 7, 70, 2, 2, 1131, 144, 3, 2, 2, 2, 1132, 1133, 7, 74, 2, 2, 1133, 1134, 7, 81, 2, 2, 1134, 1135, 7, 87, 2, 2, 1135, 1136, 7, 84, 2, 2, 1136, 1137, 7, 97, 2, 2, 1137, 1138, 7, 79, 2, 2, 1138, 1139, 7, 75, 2, 2, 1139, 1140, 7, 80, 2, 2, 1140, 1141, 7, 87, 2, 2, 1141, 1142, 7, 86, 2, 2, 1142, 1143, 7, 71, 2, 2, 1143, 146, 3, 2, 2, 2, 1144, 1145, 7, 70, 2, 2, 1145, 1146, 7, 67, 2, 2, 1146, 1147, 7, 91, 2, 2, 1147, 1148, 7, 97, 2, 2, 1148, 1149, 7, 79, 2, 2, 1149, 1150, 7, 75, 2, 2, 1150, 1151, 7, 69, 2, 2, 1151, 1152, 7, 84, 2, 2, 1152, 1153, 7, 81, 2, 2, 1153, 1154, 7, 85, 2, 2, 1154, 1155, 7, 71, 2, 2, 1155, 1156, 7, 69, 2, 2, 1156, 1157, 7, 81, 2, 2, 1157, 1158, 7, 80, 2, 2, 1158, 1159, 7, 70, 2, 2, 1159, 148, 3, 2, 2, 2, 1160, 1161, 7, 70, 2, 2, 1161, 1162, 7, 67, 2, 2, 1162, 1163, 7, 91, 2, 2, 1163, 1164, 7, 97, 2, 2, 1164, 1165, 7, 85, 2, 2, 1165, 1166, 7, 71, 2, 2, 1166, 1167, 7, 69, 2, 2, 1167, 1168, 7, 81, 2, 2, 1168, 1169, 7, 80, 2, 2, 1169, 1170, 7, 70, 2, 2, 1170, 150, 3, 2, 2, 2, 1171, 1172, 7, 70, 2, 2, 1172, 1173, 7, 67, 2, 2, 1173, 1174, 7, 91, 2, 2, 1174, 1175, 7, 97, 2, 2, 1175, 1176, 7, 79, 2, 2, 1176, 1177, 7, 75, 2, 2, 1177, 1178, 7, 80, 2, 2, 1178, 1179, 7, 87, 2, 2, 1179, 1180, 7, 86, 2, 2, 1180, 1181, 7, 71, 2, 2, 1181, 152, 3, 2, 2, 2, 1182, 1183, 7, 70, 2, 2, 1183, 1184, 7, 67, 2, 2, 1184, 1185, 7, 91, 2, 2, 1185, 1186, 7, 97, 2, 2, 1186, 1187, 7, 74, 2, 2, 1187, 1188, 7, 81, 2, 2, 1188, 1189, 7, 87, 2, 2, 1189, 1190, 7, 84, 2, 2, 1190, 154, 3, 2, 2, 2, 1191, 1192, 7, 91, 2, 2, 1192, 1193, 7, 71, 2, 2, 1193, 1194, 7, 67, 2, 2, 1194, 1195, 7, 84, 2, 2, 1195, 1196, 7, 97, 2, 2, 1196, 1197, 7, 79, 2, 2, 1197, 1198, 7, 81, 2, 2, 1198, 1199, 7, 80, 2, 2, 1199, 1200, 7, 86, 2, 2, 1200, 1201, 7, 74, 2, 2, 1201, 156, 3, 2, 2, 2, 1202, 1203, 7, 70, 2, 2, 1203, 1204, 7, 67, 2, 2, 1204, 1205, 7, 86, 2, 2, 1205, 1206, 7, 67, 2, 2, 1206, 1207, 7, 79, 2, 2, 1207, 1208, 7, 81, 2, 2, 1208, 1209, 7, 70, 2, 2, 1209, 1210, 7, 71, 2, 2, 1210, 1211, 7, 78, 2, 2, 1211, 158, 3, 2, 2, 2, 1212, 1213, 7, 78, 2, 2, 1213, 1214, 7, 81, 2, 2, 1214, 1215, 7, 81, 2, 2, 1215, 1216, 7, 77, 2, 2, 1216, 1217, 7, 87, 2, 2, 1217, 1218, 7, 82, 2, 2, 1218, 160, 3, 2, 2, 2, 1219, 1220, 7, 85, 2, 2, 1220, 1221, 7, 67, 2, 2, 1221, 1222, 7, 88, 2, 2, 1222, 1223, 7, 71, 2, 2, 1223, 1224, 7, 70, 2, 2, 1224, 1225, 7, 85, 2, 2, 1225, 1226, 7, 71, 2, 2, 1226, 1227, 7, 67, 2, 2, 1227, 1228, 7, 84, 2, 2, 1228, 1229, 7, 69, 2, 2, 1229, 1230, 7, 74, 2, 2, 1230, 162, 3, 2, 2, 2, 1231, 1232, 7, 75, 2, 2, 1232, 1233, 7, 80, 2, 2, 1233, 1234, 7, 86, 2, 2, 1234, 164, 3, 2, 2, 2, 1235, 1236, 7, 75, 2, 2, 1236, 1237, 7, 80, 2, 2, 1237, 1238, 7, 86, 2, 2, 1238, 1239, 7, 71, 2, 2, 1239, 1240, 7, 73, 2, 2, 1240, 1241, 7, 71, 2, 2, 1241, 1242, 7, 84, 2, 2, 1242, 166, 3, 2, 2, 2, 1243, 1244, 7, 70, 2, 2, 1244, 1245, 7, 81, 2, 2, 1245, 1246, 7, 87, 2, 2, 1246, 1247, 7, 68, 2, 2, 1247, 1248, 7, 78, 2, 2, 1248, 1249, 7, 71, 2, 2, 1249, 168, 3, 2, 2, 2, 1250, 1251, 7, 78, 2, 2, 1251, 1252, 7, 81, 2, 2, 1252, 1253, 7, 80, 2, 2, 1253, 1254, 7, 73, 2, 2, 1254, 170, 3, 2, 2, 2, 1255, 1256, 7, 72, 2, 2, 1256, 1257, 7, 78, 2, 2, 1257, 1258, 7, 81, 2, 2, 1258, 1259, 7, 67, 2, 2, 1259, 1260, 7, 86, 2, 2, 1260, 172, 3, 2, 2, 2, 1261, 1262, 7, 85, 2, 2, 1262, 1263, 7, 86, 2, 2, 1263, 1264, 7, 84, 2, 2, 1264, 1265, 7, 75, 2, 2, 1265, 1266, 7, 80, 2, 2, 1266, 1267, 7, 73, 2, 2, 1267, 174, 3, 2, 2, 2, 1268, 1269, 7, 68, 2, 2, 1269, 1270, 7, 81, 2, 2, 1270, 1271, 7, 81, 2, 2, 1271, 1272, 7, 78, 2, 2, 1272, 1273, 7, 71, 2, 2, 1273, 1274, 7, 67, 2, 2, 1274, 1275, 7, 80, 2, 2, 1275, 176, 3, 2, 2, 2, 1276, 1277, 7, 126, 2, 2, 1277, 178, 3, 2, 2, 2, 1278, 1279, 7, 46, 2, 2, 1279, 180, 3, 2, 2, 2, 1280, 1281, 7, 48, 2, 2, 1281, 182, 3, 2, 2, 2, 1282, 1283, 7, 63, 2, 2, 1283, 184, 3, 2, 2, 2, 1284, 1285, 7, 64, 2, 2, 1285, 186, 3, 2, 2, 2, 1286, 1287, 7, 62, 2, 2, 1287, 188, 3, 2, 2, 2, 1288, 1289, 7, 62, 2, 2, 1289, 1290, 7, 63, 2, 2, 1290, 190, 3, 2, 2, 2, 1291, 1292, 7, 64, 2, 2, 1292, 1293, 7, 63, 2, 2, 1293, 192, 3, 2, 2, 2, 1294, 1295, 7, 35, 2, 2, 1295, 1296, 7, 63, 2, 2, 1296, 194, 3, 2, 2, 2, 1297, 1298, 7, 45, 2, 2, 1298, 196, 3, 2, 2, 2, 1299, 1300, 7, 47, 2, 2, 1300, 198, 3, 2, 2, 2, 1301, 1302, 7, 44, 2, 2, 1302, 200, 3, 2, 2, 2, 1303, 1304, 7, 49, 2, 2, 1304, 202, 3, 2, 2, 2, 1305, 1306, 7, 39, 2, 2, 1306, 204, 3, 2, 2, 2, 1307, 1308, 7, 35, 2, 2, 1308, 206, 3, 2, 2, 2, 1309, 1310, 7, 60, 2, 2, 1310, 208, 3, 2, 2, 2, 1311, 1312, 7, 42, 2, 2, 1312, 210, 3, 2, 2, 2, 1313, 1314, 7, 43, 2, 2, 1314, 212, 3, 2, 2, 2, 1315, 1316, 7, 93, 2, 2, 1316, 214, 3, 2, 2, 2, 1317, 1318, 7, 95, 2, 2, 1318, 216, 3, 2, 2, 2, 1319, 1320, 7, 41, 2, 2, 1320, 218, 3, 2, 2, 2, 1321, 1322, 7, 36, 2, 2, 1322, 220, 3, 2, 2, 2, 1323, 1324, 7, 98, 2, 2, 1324, 222, 3, 2, 2, 2, 1325, 1326, 7, 128, 2, 2, 1326, 224, 3, 2, 2, 2, 1327, 1328, 7, 40, 2, 2, 1328, 226, 3, 2, 2, 2, 1329, 1330, 7, 96, 2, 2, 1330, 228, 3, 2, 2, 2, 1331, 1332, 7, 67, 2, 2, 1332, 1333, 7, 88, 2, 2, 1333, 1334, 7, 73, 2, 2, 1334, 230, 3, 2, 2, 2, 1335, 1336, 7, 69, 2, 2, 1336, 1337, 7, 81, 2, 2, 1337, 1338, 7, 87, 2, 2, 1338, 1339, 7, 80, 2, 2, 1339, 1340, 7, 86, 2, 2, 1340, 232, 3, 2, 2, 2, 1341, 1342, 7, 70, 2, 2, 1342, 1343, 7, 75, 2, 2, 1343, 1344, 7, 85, 2, 2, 1344, 1345, 7, 86, 2, 2, 1345, 1346, 7, 75, 2, 2, 1346, 1347, 7, 80, 2, 2, 1347, 1348, 7, 69, 2, 2, 1348, 1349, 7, 86, 2, 2, 1349, 1350, 7, 97, 2, 2, 1350, 1351, 7, 69, 2, 2, 1351, 1352, 7, 81, 2, 2, 1352, 1353, 7, 87, 2, 2, 1353, 1354, 7, 80, 2, 2, 1354, 1355, 7, 86, 2, 2, 1355, 234, 3, 2, 2, 2, 1356, 1357, 7, 71, 2, 2, 1357, 1358, 7, 85, 2, 2, 1358, 1359, 7, 86, 2, 2, 1359, 1360, 7, 70, 2, 2, 1360, 1361, 7, 69, 2, 2, 1361, 236, 3, 2, 2, 2, 1362, 1363, 7, 71, 2, 2, 1363, 1364, 7, 85, 2, 2, 1364, 1365, 7, 86, 2, 2, 1365, 1366, 7, 70, 2, 2, 1366, 1367, 7, 69, 2, 2, 1367, 1368, 7, 97, 2, 2, 1368, 1369, 7, 71, 2, 2, 1369, 1370, 7, 84, 2, 2, 1370, 1371, 7, 84, 2, 2, 1371, 1372, 7, 81, 2, 2, 1372, 1373, 7, 84, 2, 2, 1373, 238, 3, 2, 2, 2, 1374, 1375, 7, 79, 2, 2, 1375, 1376, 7, 67, 2, 2, 1376, 1377, 7, 90, 2, 2, 1377, 240, 3, 2, 2, 2, 1378, 1379, 7, 79, 2, 2, 1379, 1380, 7, 71, 2, 2, 1380, 1381, 7, 67, 2, 2, 1381, 1382, 7, 80, 2, 2, 1382, 242, 3, 2, 2, 2, 1383, 1384, 7, 79, 2, 2, 1384, 1385, 7, 71, 2, 2, 1385, 1386, 7, 70, 2, 2, 1386, 1387, 7, 75, 2, 2, 1387, 1388, 7, 67, 2, 2, 1388, 1389, 7, 80, 2, 2, 1389, 244, 3, 2, 2, 2, 1390, 1391, 7, 79, 2, 2, 1391, 1392, 7, 75, 2, 2, 1392, 1393, 7, 80, 2, 2, 1393, 246, 3, 2, 2, 2, 1394, 1395, 7, 79, 2, 2, 1395, 1396, 7, 81, 2, 2, 1396, 1397, 7, 70, 2, 2, 1397, 1398, 7, 71, 2, 2, 1398, 248, 3, 2, 2, 2, 1399, 1400, 7, 84, 2, 2, 1400, 1401, 7, 67, 2, 2, 1401, 1402, 7, 80, 2, 2, 1402, 1403, 7, 73, 2, 2, 1403, 1404, 7, 71, 2, 2, 1404, 250, 3, 2, 2, 2, 1405, 1406, 7, 85, 2, 2, 1406, 1407, 7, 86, 2, 2, 1407, 1408, 7, 70, 2, 2, 1408, 1409, 7, 71, 2, 2, 1409, 1410, 7, 88, 2, 2, 1410, 252, 3, 2, 2, 2, 1411, 1412, 7, 85, 2, 2, 1412, 1413, 7, 86, 2, 2, 1413, 1414, 7, 70, 2, 2, 1414, 1415, 7, 71, 2, 2, 1415, 1416, 7, 88, 2, 2, 1416, 1417, 7, 82, 2, 2, 1417, 254, 3, 2, 2, 2, 1418, 1419, 7, 85, 2, 2, 1419, 1420, 7, 87, 2, 2, 1420, 1421, 7, 79, 2, 2, 1421, 256, 3, 2, 2, 2, 1422, 1423, 7, 85, 2, 2, 1423, 1424, 7, 87, 2, 2, 1424, 1425, 7, 79, 2, 2, 1425, 1426, 7, 85, 2, 2, 1426, 1427, 7, 83, 2, 2, 1427, 258, 3, 2, 2, 2, 1428, 1429, 7, 88, 2, 2, 1429, 1430, 7, 67, 2, 2, 1430, 1431, 7, 84, 2, 2, 1431, 1432, 7, 97, 2, 2, 1432, 1433, 7, 85, 2, 2, 1433, 1434, 7, 67, 2, 2, 1434, 1435, 7, 79, 2, 2, 1435, 1436, 7, 82, 2, 2, 1436, 260, 3, 2, 2, 2, 1437, 1438, 7, 88, 2, 2, 1438, 1439, 7, 67, 2, 2, 1439, 1440, 7, 84, 2, 2, 1440, 1441, 7, 97, 2, 2, 1441, 1442, 7, 82, 2, 2, 1442, 1443, 7, 81, 2, 2, 1443, 1444, 7, 82, 2, 2, 1444, 262, 3, 2, 2, 2, 1445, 1446, 7, 85, 2, 2, 1446, 1447, 7, 86, 2, 2, 1447, 1448, 7, 70, 2, 2, 1448, 1449, 7, 70, 2, 2, 1449, 1450, 7, 71, 2, 2, 1450, 1451, 7, 88, 2, 2, 1451, 1452, 7, 97, 2, 2, 1452, 1453, 7, 85, 2, 2, 1453, 1454, 7, 67, 2, 2, 1454, 1455, 7, 79, 2, 2, 1455, 1456, 7, 82, 2, 2, 1456, 264, 3, 2, 2, 2, 1457, 1458, 7, 85, 2, 2, 1458, 1459, 7, 86, 2, 2, 1459, 1460, 7, 70, 2, 2, 1460, 1461, 7, 70, 2, 2, 1461, 1462, 7, 71, 2, 2, 1462, 1463, 7, 88, 2, 2, 1463, 1464, 7, 97, 2, 2, 1464, 1465, 7, 82, 2, 2, 1465, 1466, 7, 81, 2, 2, 1466, 1467, 7, 82, 2, 2, 1467, 266, 3, 2, 2, 2, 1468, 1469, 7, 82, 2, 2, 1469, 1470, 7, 71, 2, 2, 1470, 1471, 7, 84, 2, 2, 1471, 1472, 7, 69, 2, 2, 1472, 1473, 7, 71, 2, 2, 1473, 1474, 7, 80, 2, 2, 1474, 1475, 7, 86, 2, 2, 1475, 1476, 7, 75, 2, 2, 1476, 1477, 7, 78, 2, 2, 1477, 1478, 7, 71, 2, 2, 1478, 268, 3, 2, 2, 2, 1479, 1480, 7, 72, 2, 2, 1480, 1481, 7, 75, 2, 2, 1481, 1482, 7, 84, 2, 2, 1482, 1483, 7, 85, 2, 2, 1483, 1484, 7, 86, 2, 2, 1484, 270, 3, 2, 2, 2, 1485, 1486, 7, 78, 2, 2, 1486, 1487, 7, 67, 2, 2, 1487, 1488, 7, 85, 2, 2, 1488, 1489, 7, 86, 2, 2, 1489, 272, 3, 2, 2, 2, 1490, 1491, 7, 78, 2, 2, 1491, 1492, 7, 75, 2, 2, 1492, 1493, 7, 85, 2, 2, 1493, 1494, 7, 86, 2, 2, 1494, 274, 3, 2, 2, 2, 1495, 1496, 7, 88, 2, 2, 1496, 1497, 7, 67, 2, 2, 1497, 1498, 7, 78, 2, 2, 1498, 1499, 7, 87, 2, 2, 1499, 1500, 7, 71, 2, 2, 1500, 1501, 7, 85, 2, 2, 1501, 276, 3, 2, 2, 2, 1502, 1503, 7, 71, 2, 2, 1503, 1504, 7, 67, 2, 2, 1504, 1505, 7, 84, 2, 2, 1505, 1506, 7, 78, 2, 2, 1506, 1507, 7, 75, 2, 2, 1507, 1508, 7, 71, 2, 2, 1508, 1509, 7, 85, 2, 2, 1509, 1510, 7, 86, 2, 2, 1510, 278, 3, 2, 2, 2, 1511, 1512, 7, 71, 2, 2, 1512, 1513, 7, 67, 2, 2, 1513, 1514, 7, 84, 2, 2, 1514, 1515, 7, 78, 2, 2, 1515, 1516, 7, 75, 2, 2, 1516, 1517, 7, 71, 2, 2, 1517, 1518, 7, 85, 2, 2, 1518, 1519, 7, 86, 2, 2, 1519, 1520, 7, 97, 2, 2, 1520, 1521, 7, 86, 2, 2, 1521, 1522, 7, 75, 2, 2, 1522, 1523, 7, 79, 2, 2, 1523, 1524, 7, 71, 2, 2, 1524, 280, 3, 2, 2, 2, 1525, 1526, 7, 78, 2, 2, 1526, 1527, 7, 67, 2, 2, 1527, 1528, 7, 86, 2, 2, 1528, 1529, 7, 71, 2, 2, 1529, 1530, 7, 85, 2, 2, 1530, 1531, 7, 86, 2, 2, 1531, 282, 3, 2, 2, 2, 1532, 1533, 7, 78, 2, 2, 1533, 1534, 7, 67, 2, 2, 1534, 1535, 7, 86, 2, 2, 1535, 1536, 7, 71, 2, 2, 1536, 1537, 7, 85, 2, 2, 1537, 1538, 7, 86, 2, 2, 1538, 1539, 7, 97, 2, 2, 1539, 1540, 7, 86, 2, 2, 1540, 1541, 7, 75, 2, 2, 1541, 1542, 7, 79, 2, 2, 1542, 1543, 7, 71, 2, 2, 1543, 284, 3, 2, 2, 2, 1544, 1545, 7, 82, 2, 2, 1545, 1546, 7, 71, 2, 2, 1546, 1547, 7, 84, 2, 2, 1547, 1548, 7, 97, 2, 2, 1548, 1549, 7, 70, 2, 2, 1549, 1550, 7, 67, 2, 2, 1550, 1551, 7, 91, 2, 2, 1551, 286, 3, 2, 2, 2, 1552, 1553, 7, 82, 2, 2, 1553, 1554, 7, 71, 2, 2, 1554, 1555, 7, 84, 2, 2, 1555, 1556, 7, 97, 2, 2, 1556, 1557, 7, 74, 2, 2, 1557, 1558, 7, 81, 2, 2, 1558, 1559, 7, 87, 2, 2, 1559, 1560, 7, 84, 2, 2, 1560, 288, 3, 2, 2, 2, 1561, 1562, 7, 82, 2, 2, 1562, 1563, 7, 71, 2, 2, 1563, 1564, 7, 84, 2, 2, 1564, 1565, 7, 97, 2, 2, 1565, 1566, 7, 79, 2, 2, 1566, 1567, 7, 75, 2, 2, 1567, 1568, 7, 80, 2, 2, 1568, 1569, 7, 87, 2, 2, 1569, 1570, 7, 86, 2, 2, 1570, 1571, 7, 71, 2, 2, 1571, 290, 3, 2, 2, 2, 1572, 1573, 7, 82, 2, 2, 1573, 1574, 7, 71, 2, 2, 1574, 1575, 7, 84, 2, 2, 1575, 1576, 7, 97, 2, 2, 1576, 1577, 7, 85, 2, 2, 1577, 1578, 7, 71, 2, 2, 1578, 1579, 7, 69, 2, 2, 1579, 1580, 7, 81, 2, 2, 1580, 1581, 7, 80, 2, 2, 1581, 1582, 7, 70, 2, 2, 1582, 292, 3, 2, 2, 2, 1583, 1584, 7, 84, 2, 2, 1584, 1585, 7, 67, 2, 2, 1585, 1586, 7, 86, 2, 2, 1586, 1587, 7, 71, 2, 2, 1587, 294, 3, 2, 2, 2, 1588, 1589, 7, 85, 2, 2, 1589, 1590, 7, 82, 2, 2, 1590, 1591, 7, 67, 2, 2, 1591, 1592, 7, 84, 2, 2, 1592, 1593, 7, 77, 2, 2, 1593, 1594, 7, 78, 2, 2, 1594, 1595, 7, 75, 2, 2, 1595, 1596, 7, 80, 2, 2, 1596, 1597, 7, 71, 2, 2, 1597, 296, 3, 2, 2, 2, 1598, 1599, 7, 69, 2, 2, 1599, 298, 3, 2, 2, 2, 1600, 1601, 7, 70, 2, 2, 1601, 1602, 7, 69, 2, 2, 1602, 300, 3, 2, 2, 2, 1603, 1604, 7, 67, 2, 2, 1604, 1605, 7, 68, 2, 2, 1605, 1606, 7, 85, 2, 2, 1606, 302, 3, 2, 2, 2, 1607, 1608, 7, 69, 2, 2, 1608, 1609, 7, 71, 2, 2, 1609, 1610, 7, 75, 2, 2, 1610, 1611, 7, 78, 2, 2, 1611, 304, 3, 2, 2, 2, 1612, 1613, 7, 69, 2, 2, 1613, 1614, 7, 71, 2, 2, 1614, 1615, 7, 75, 2, 2, 1615, 1616, 7, 78, 2, 2, 1616, 1617, 7, 75, 2, 2, 1617, 1618, 7, 80, 2, 2, 1618, 1619, 7, 73, 2, 2, 1619, 306, 3, 2, 2, 2, 1620, 1621, 7, 69, 2, 2, 1621, 1622, 7, 81, 2, 2, 1622, 1623, 7, 80, 2, 2, 1623, 1624, 7, 88, 2, 2, 1624, 308, 3, 2, 2, 2, 1625, 1626, 7, 69, 2, 2, 1626, 1627, 7, 84, 2, 2, 1627, 1628, 7, 69, 2, 2, 1628, 1629, 7, 53, 2, 2, 1629, 1630, 7, 52, 2, 2, 1630, 310, 3, 2, 2, 2, 1631, 1632, 7, 71, 2, 2, 1632, 312, 3, 2, 2, 2, 1633, 1634, 7, 71, 2, 2, 1634, 1635, 7, 90, 2, 2, 1635, 1636, 7, 82, 2, 2, 1636, 314, 3, 2, 2, 2, 1637, 1638, 7, 72, 2, 2, 1638, 1639, 7, 78, 2, 2, 1639, 1640, 7, 81, 2, 2, 1640, 1641, 7, 81, 2, 2, 1641, 1642, 7, 84, 2, 2, 1642, 316, 3, 2, 2, 2, 1643, 1644, 7, 78, 2, 2, 1644, 1645, 7, 80, 2, 2, 1645, 318, 3, 2, 2, 2, 1646, 1647, 7, 78, 2, 2, 1647, 1648, 7, 81, 2, 2, 1648, 1649, 7, 73, 2, 2, 1649, 320, 3, 2, 2, 2, 1650, 1651, 7, 78, 2, 2, 1651, 1652, 7, 81, 2, 2, 1652, 1653, 7, 73, 2, 2, 1653, 1654, 7, 51, 2, 2, 1654, 1655, 7, 50, 2, 2, 1655, 322, 3, 2, 2, 2, 1656, 1657, 7, 78, 2, 2, 1657, 1658, 7, 81, 2, 2, 1658, 1659, 7, 73, 2, 2, 1659, 1660, 7, 52, 2, 2, 1660, 324, 3, 2, 2, 2, 1661, 1662, 7, 79, 2, 2, 1662, 1663, 7, 81, 2, 2, 1663, 1664, 7, 70, 2, 2, 1664, 326, 3, 2, 2, 2, 1665, 1666, 7, 82, 2, 2, 1666, 1667, 7, 75, 2, 2, 1667, 328, 3, 2, 2, 2, 1668, 1669, 7, 82, 2, 2, 1669, 1670, 7, 81, 2, 2, 1670, 1671, 7, 89, 2, 2, 1671, 330, 3, 2, 2, 2, 1672, 1673, 7, 82, 2, 2, 1673, 1674, 7, 81, 2, 2, 1674, 1675, 7, 89, 2, 2, 1675, 1676, 7, 71, 2, 2, 1676, 1677, 7, 84, 2, 2, 1677, 332, 3, 2, 2, 2, 1678, 1679, 7, 84, 2, 2, 1679, 1680, 7, 67, 2, 2, 1680, 1681, 7, 80, 2, 2, 1681, 1682, 7, 70, 2, 2, 1682, 334, 3, 2, 2, 2, 1683, 1684, 7, 84, 2, 2, 1684, 1685, 7, 81, 2, 2, 1685, 1686, 7, 87, 2, 2, 1686, 1687, 7, 80, 2, 2, 1687, 1688, 7, 70, 2, 2, 1688, 336, 3, 2, 2, 2, 1689, 1690, 7, 85, 2, 2, 1690, 1691, 7, 75, 2, 2, 1691, 1692, 7, 73, 2, 2, 1692, 1693, 7, 80, 2, 2, 1693, 338, 3, 2, 2, 2, 1694, 1695, 7, 85, 2, 2, 1695, 1696, 7, 83, 2, 2, 1696, 1697, 7, 84, 2, 2, 1697, 1698, 7, 86, 2, 2, 1698, 340, 3, 2, 2, 2, 1699, 1700, 7, 86, 2, 2, 1700, 1701, 7, 84, 2, 2, 1701, 1702, 7, 87, 2, 2, 1702, 1703, 7, 80, 2, 2, 1703, 1704, 7, 69, 2, 2, 1704, 1705, 7, 67, 2, 2, 1705, 1706, 7, 86, 2, 2, 1706, 1707, 7, 71, 2, 2, 1707, 342, 3, 2, 2, 2, 1708, 1709, 7, 67, 2, 2, 1709, 1710, 7, 69, 2, 2, 1710, 1711, 7, 81, 2, 2, 1711, 1712, 7, 85, 2, 2, 1712, 344, 3, 2, 2, 2, 1713, 1714, 7, 67, 2, 2, 1714, 1715, 7, 85, 2, 2, 1715, 1716, 7, 75, 2, 2, 1716, 1717, 7, 80, 2, 2, 1717, 346, 3, 2, 2, 2, 1718, 1719, 7, 67, 2, 2, 1719, 1720, 7, 86, 2, 2, 1720, 1721, 7, 67, 2, 2, 1721, 1722, 7, 80, 2, 2, 1722, 348, 3, 2, 2, 2, 1723, 1724, 7, 67, 2, 2, 1724, 1725, 7, 86, 2, 2, 1725, 1726, 7, 67, 2, 2, 1726, 1727, 7, 80, 2, 2, 1727, 1728, 7, 52, 2, 2, 1728, 350, 3, 2, 2, 2, 1729, 1730, 7, 69, 2, 2, 1730, 1731, 7, 81, 2, 2, 1731, 1732, 7, 85, 2, 2, 1732, 352, 3, 2, 2, 2, 1733, 1734, 7, 69, 2, 2, 1734, 1735, 7, 81, 2, 2, 1735, 1736, 7, 86, 2, 2, 1736, 354, 3, 2, 2, 2, 1737, 1738, 7, 70, 2, 2, 1738, 1739, 7, 71, 2, 2, 1739, 1740, 7, 73, 2, 2, 1740, 1741, 7, 84, 2, 2, 1741, 1742, 7, 71, 2, 2, 1742, 1743, 7, 71, 2, 2, 1743, 1744, 7, 85, 2, 2, 1744, 356, 3, 2, 2, 2, 1745, 1746, 7, 84, 2, 2, 1746, 1747, 7, 67, 2, 2, 1747, 1748, 7, 70, 2, 2, 1748, 1749, 7, 75, 2, 2, 1749, 1750, 7, 67, 2, 2, 1750, 1751, 7, 80, 2, 2, 1751, 1752, 7, 85, 2, 2, 1752, 358, 3, 2, 2, 2, 1753, 1754, 7, 85, 2, 2, 1754, 1755, 7, 75, 2, 2, 1755, 1756, 7, 80, 2, 2, 1756, 360, 3, 2, 2, 2, 1757, 1758, 7, 86, 2, 2, 1758, 1759, 7, 67, 2, 2, 1759, 1760, 7, 80, 2, 2, 1760, 362, 3, 2, 2, 2, 1761, 1762, 7, 67, 2, 2, 1762, 1763, 7, 70, 2, 2, 1763, 1764, 7, 70, 2, 2, 1764, 1765, 7, 70, 2, 2, 1765, 1766, 7, 67, 2, 2, 1766, 1767, 7, 86, 2, 2, 1767, 1768, 7, 71, 2, 2, 1768, 364, 3, 2, 2, 2, 1769, 1770, 7, 70, 2, 2, 1770, 1771, 7, 67, 2, 2, 1771, 1772, 7, 86, 2, 2, 1772, 1773, 7, 71, 2, 2, 1773, 366, 3, 2, 2, 2, 1774, 1775, 7, 70, 2, 2, 1775, 1776, 7, 67, 2, 2, 1776, 1777, 7, 86, 2, 2, 1777, 1778, 7, 71, 2, 2, 1778, 1779, 7, 97, 2, 2, 1779, 1780, 7, 67, 2, 2, 1780, 1781, 7, 70, 2, 2, 1781, 1782, 7, 70, 2, 2, 1782, 368, 3, 2, 2, 2, 1783, 1784, 7, 70, 2, 2, 1784, 1785, 7, 67, 2, 2, 1785, 1786, 7, 86, 2, 2, 1786, 1787, 7, 71, 2, 2, 1787, 1788, 7, 97, 2, 2, 1788, 1789, 7, 85, 2, 2, 1789, 1790, 7, 87, 2, 2, 1790, 1791, 7, 68, 2, 2, 1791, 370, 3, 2, 2, 2, 1792, 1793, 7, 70, 2, 2, 1793, 1794, 7, 67, 2, 2, 1794, 1795, 7, 91, 2, 2, 1795, 1796, 7, 81, 2, 2, 1796, 1797, 7, 72, 2, 2, 1797, 1798, 7, 79, 2, 2, 1798, 1799, 7, 81, 2, 2, 1799, 1800, 7, 80, 2, 2, 1800, 1801, 7, 86, 2, 2, 1801, 1802, 7, 74, 2, 2, 1802, 372, 3, 2, 2, 2, 1803, 1804, 7, 70, 2, 2, 1804, 1805, 7, 67, 2, 2, 1805, 1806, 7, 91, 2, 2, 1806, 1807, 7, 81, 2, 2, 1807, 1808, 7, 72, 2, 2, 1808, 1809, 7, 89, 2, 2, 1809, 1810, 7, 71, 2, 2, 1810, 1811, 7, 71, 2, 2, 1811, 1812, 7, 77, 2, 2, 1812, 374, 3, 2, 2, 2, 1813, 1814, 7, 70, 2, 2, 1814, 1815, 7, 67, 2, 2, 1815, 1816, 7, 91, 2, 2, 1816, 1817, 7, 81, 2, 2, 1817, 1818, 7, 72, 2, 2, 1818, 1819, 7, 91, 2, 2, 1819, 1820, 7, 71, 2, 2, 1820, 1821, 7, 67, 2, 2, 1821, 1822, 7, 84, 2, 2, 1822, 376, 3, 2, 2, 2, 1823, 1824, 7, 70, 2, 2, 1824, 1825, 7, 67, 2, 2, 1825, 1826, 7, 91, 2, 2, 1826, 1827, 7, 80, 2, 2, 1827, 1828, 7, 67, 2, 2, 1828, 1829, 7, 79, 2, 2, 1829, 1830, 7, 71, 2, 2, 1830, 378, 3, 2, 2, 2, 1831, 1832, 7, 72, 2, 2, 1832, 1833, 7, 84, 2, 2, 1833, 1834, 7, 81, 2, 2, 1834, 1835, 7, 79, 2, 2, 1835, 1836, 7, 97, 2, 2, 1836, 1837, 7, 70, 2, 2, 1837, 1838, 7, 67, 2, 2, 1838, 1839, 7, 91, 2, 2, 1839, 1840, 7, 85, 2, 2, 1840, 380, 3, 2, 2, 2, 1841, 1842, 7, 79, 2, 2, 1842, 1843, 7, 81, 2, 2, 1843, 1844, 7, 80, 2, 2, 1844, 1845, 7, 86, 2, 2, 1845, 1846, 7, 74, 2, 2, 1846, 1847, 7, 80, 2, 2, 1847, 1848, 7, 67, 2, 2, 1848, 1849, 7, 79, 2, 2, 1849, 1850, 7, 71, 2, 2, 1850, 382, 3, 2, 2, 2, 1851, 1852, 7, 85, 2, 2, 1852, 1853, 7, 87, 2, 2, 1853, 1854, 7, 68, 2, 2, 1854, 1855, 7, 70, 2, 2, 1855, 1856, 7, 67, 2, 2, 1856, 1857, 7, 86, 2, 2, 1857, 1858, 7, 71, 2, 2, 1858, 384, 3, 2, 2, 2, 1859, 1860, 7, 86, 2, 2, 1860, 1861, 7, 75, 2, 2, 1861, 1862, 7, 79, 2, 2, 1862, 1863, 7, 71, 2, 2, 1863, 386, 3, 2, 2, 2, 1864, 1865, 7, 86, 2, 2, 1865, 1866, 7, 75, 2, 2, 1866, 1867, 7, 79, 2, 2, 1867, 1868, 7, 71, 2, 2, 1868, 1869, 7, 97, 2, 2, 1869, 1870, 7, 86, 2, 2, 1870, 1871, 7, 81, 2, 2, 1871, 1872, 7, 97, 2, 2, 1872, 1873, 7, 85, 2, 2, 1873, 1874, 7, 71, 2, 2, 1874, 1875, 7, 69, 2, 2, 1875, 388, 3, 2, 2, 2, 1876, 1877, 7, 86, 2, 2, 1877, 1878, 7, 75, 2, 2, 1878, 1879, 7, 79, 2, 2, 1879, 1880, 7, 71, 2, 2, 1880, 1881, 7, 85, 2, 2, 1881, 1882, 7, 86, 2, 2, 1882, 1883, 7, 67, 2, 2, 1883, 1884, 7, 79, 2, 2, 1884, 1885, 7, 82, 2, 2, 1885, 390, 3, 2, 2, 2, 1886, 1887, 7, 70, 2, 2, 1887, 1888, 7, 67, 2, 2, 1888, 1889, 7, 86, 2, 2, 1889, 1890, 7, 71, 2, 2, 1890, 1891, 7, 97, 2, 2, 1891, 1892, 7, 72, 2, 2, 1892, 1893, 7, 81, 2, 2, 1893, 1894, 7, 84, 2, 2, 1894, 1895, 7, 79, 2, 2, 1895, 1896, 7, 67, 2, 2, 1896, 1897, 7, 86, 2, 2, 1897, 392, 3, 2, 2, 2, 1898, 1899, 7, 86, 2, 2, 1899, 1900, 7, 81, 2, 2, 1900, 1901, 7, 97, 2, 2, 1901, 1902, 7, 70, 2, 2, 1902, 1903, 7, 67, 2, 2, 1903, 1904, 7, 91, 2, 2, 1904, 1905, 7, 85, 2, 2, 1905, 394, 3, 2, 2, 2, 1906, 1907, 7, 85, 2, 2, 1907, 1908, 7, 87, 2, 2, 1908, 1909, 7, 68, 2, 2, 1909, 1910, 7, 85, 2, 2, 1910, 1911, 7, 86, 2, 2, 1911, 1912, 7, 84, 2, 2, 1912, 396, 3, 2, 2, 2, 1913, 1914, 7, 85, 2, 2, 1914, 1915, 7, 87, 2, 2, 1915, 1916, 7, 68, 2, 2, 1916, 1917, 7, 85, 2, 2, 1917, 1918, 7, 86, 2, 2, 1918, 1919, 7, 84, 2, 2, 1919, 1920, 7, 75, 2, 2, 1920, 1921, 7, 80, 2, 2, 1921, 1922, 7, 73, 2, 2, 1922, 398, 3, 2, 2, 2, 1923, 1924, 7, 78, 2, 2, 1924, 1925, 7, 86, 2, 2, 1925, 1926, 7, 84, 2, 2, 1926, 1927, 7, 75, 2, 2, 1927, 1928, 7, 79, 2, 2, 1928, 400, 3, 2, 2, 2, 1929, 1930, 7, 84, 2, 2, 1930, 1931, 7, 86, 2, 2, 1931, 1932, 7, 84, 2, 2, 1932, 1933, 7, 75, 2, 2, 1933, 1934, 7, 79, 2, 2, 1934, 402, 3, 2, 2, 2, 1935, 1936, 7, 86, 2, 2, 1936, 1937, 7, 84, 2, 2, 1937, 1938, 7, 75, 2, 2, 1938, 1939, 7, 79, 2, 2, 1939, 404, 3, 2, 2, 2, 1940, 1941, 7, 86, 2, 2, 1941, 1942, 7, 81, 2, 2, 1942, 406, 3, 2, 2, 2, 1943, 1944, 7, 78, 2, 2, 1944, 1945, 7, 81, 2, 2, 1945, 1946, 7, 89, 2, 2, 1946, 1947, 7, 71, 2, 2, 1947, 1948, 7, 84, 2, 2, 1948, 408, 3, 2, 2, 2, 1949, 1950, 7, 87, 2, 2, 1950, 1951, 7, 82, 2, 2, 1951, 1952, 7, 82, 2, 2, 1952, 1953, 7, 71, 2, 2, 1953, 1954, 7, 84, 2, 2, 1954, 410, 3, 2, 2, 2, 1955, 1956, 7, 69, 2, 2, 1956, 1957, 7, 81, 2, 2, 1957, 1958, 7, 80, 2, 2, 1958, 1959, 7, 69, 2, 2, 1959, 1960, 7, 67, 2, 2, 1960, 1961, 7, 86, 2, 2, 1961, 412, 3, 2, 2, 2, 1962, 1963, 7, 69, 2, 2, 1963, 1964, 7, 81, 2, 2, 1964, 1965, 7, 80, 2, 2, 1965, 1966, 7, 69, 2, 2, 1966, 1967, 7, 67, 2, 2, 1967, 1968, 7, 86, 2, 2, 1968, 1969, 7, 97, 2, 2, 1969, 1970, 7, 89, 2, 2, 1970, 1971, 7, 85, 2, 2, 1971, 414, 3, 2, 2, 2, 1972, 1973, 7, 78, 2, 2, 1973, 1974, 7, 71, 2, 2, 1974, 1975, 7, 80, 2, 2, 1975, 1976, 7, 73, 2, 2, 1976, 1977, 7, 86, 2, 2, 1977, 1978, 7, 74, 2, 2, 1978, 416, 3, 2, 2, 2, 1979, 1980, 7, 85, 2, 2, 1980, 1981, 7, 86, 2, 2, 1981, 1982, 7, 84, 2, 2, 1982, 1983, 7, 69, 2, 2, 1983, 1984, 7, 79, 2, 2, 1984, 1985, 7, 82, 2, 2, 1985, 418, 3, 2, 2, 2, 1986, 1987, 7, 84, 2, 2, 1987, 1988, 7, 75, 2, 2, 1988, 1989, 7, 73, 2, 2, 1989, 1990, 7, 74, 2, 2, 1990, 1991, 7, 86, 2, 2, 1991, 420, 3, 2, 2, 2, 1992, 1993, 7, 78, 2, 2, 1993, 1994, 7, 71, 2, 2, 1994, 1995, 7, 72, 2, 2, 1995, 1996, 7, 86, 2, 2, 1996, 422, 3, 2, 2, 2, 1997, 1998, 7, 67, 2, 2, 1998, 1999, 7, 85, 2, 2, 1999, 2000, 7, 69, 2, 2, 2000, 2001, 7, 75, 2, 2, 2001, 2002, 7, 75, 2, 2, 2002, 424, 3, 2, 2, 2, 2003, 2004, 7, 78, 2, 2, 2004, 2005, 7, 81, 2, 2, 2005, 2006, 7, 69, 2, 2, 2006, 2007, 7, 67, 2, 2, 2007, 2008, 7, 86, 2, 2, 2008, 2009, 7, 71, 2, 2, 2009, 426, 3, 2, 2, 2, 2010, 2011, 7, 84, 2, 2, 2011, 2012, 7, 71, 2, 2, 2012, 2013, 7, 82, 2, 2, 2013, 2014, 7, 78, 2, 2, 2014, 2015, 7, 67, 2, 2, 2015, 2016, 7, 69, 2, 2, 2016, 2017, 7, 71, 2, 2, 2017, 428, 3, 2, 2, 2, 2018, 2019, 7, 69, 2, 2, 2019, 2020, 7, 67, 2, 2, 2020, 2021, 7, 85, 2, 2, 2021, 2022, 7, 86, 2, 2, 2022, 430, 3, 2, 2, 2, 2023, 2024, 7, 78, 2, 2, 2024, 2025, 7, 75, 2, 2, 2025, 2026, 7, 77, 2, 2, 2026, 2027, 7, 71, 2, 2, 2027, 432, 3, 2, 2, 2, 2028, 2029, 7, 75, 2, 2, 2029, 2030, 7, 85, 2, 2, 2030, 2031, 7, 80, 2, 2, 2031, 2032, 7, 87, 2, 2, 2032, 2033, 7, 78, 2, 2, 2033, 2034, 7, 78, 2, 2, 2034, 434, 3, 2, 2, 2, 2035, 2036, 7, 75, 2, 2, 2036, 2037, 7, 85, 2, 2, 2037, 2038, 7, 80, 2, 2, 2038, 2039, 7, 81, 2, 2, 2039, 2040, 7, 86, 2, 2, 2040, 2041, 7, 80, 2, 2, 2041, 2042, 7, 87, 2, 2, 2042, 2043, 7, 78, 2, 2, 2043, 2044, 7, 78, 2, 2, 2044, 436, 3, 2, 2, 2, 2045, 2046, 7, 75, 2, 2, 2046, 2047, 7, 72, 2, 2, 2047, 2048, 7, 80, 2, 2, 2048, 2049, 7, 87, 2, 2, 2049, 2050, 7, 78, 2, 2, 2050, 2051, 7, 78, 2, 2, 2051, 438, 3, 2, 2, 2, 2052, 2053, 7, 80, 2, 2, 2053, 2054, 7, 87, 2, 2, 2054, 2055, 7, 78, 2, 2, 2055, 2056, 7, 78, 2, 2, 2056, 2057, 7, 75, 2, 2, 2057, 2058, 7, 72, 2, 2, 2058, 440, 3, 2, 2, 2, 2059, 2060, 7, 75, 2, 2, 2060, 2061, 7, 72, 2, 2, 2061, 442, 3, 2, 2, 2, 2062, 2063, 7, 79, 2, 2, 2063, 2064, 7, 67, 2, 2, 2064, 2065, 7, 86, 2, 2, 2065, 2066, 7, 69, 2, 2, 2066, 2067, 7, 74, 2, 2, 2067, 444, 3, 2, 2, 2, 2068, 2069, 7, 79, 2, 2, 2069, 2070, 7, 67, 2, 2, 2070, 2071, 7, 86, 2, 2, 2071, 2072, 7, 69, 2, 2, 2072, 2073, 7, 74, 2, 2, 2073, 2074, 7, 97, 2, 2, 2074, 2075, 7, 82, 2, 2, 2075, 2076, 7, 74, 2, 2, 2076, 2077, 7, 84, 2, 2, 2077, 2078, 7, 67, 2, 2, 2078, 2079, 7, 85, 2, 2, 2079, 2080, 7, 71, 2, 2, 2080, 446, 3, 2, 2, 2, 2081, 2082, 7, 85, 2, 2, 2082, 2083, 7, 75, 2, 2, 2083, 2084, 7, 79, 2, 2, 2084, 2085, 7, 82, 2, 2, 2085, 2086, 7, 78, 2, 2, 2086, 2087, 7, 71, 2, 2, 2087, 2088, 7, 97, 2, 2, 2088, 2089, 7, 83, 2, 2, 2089, 2090, 7, 87, 2, 2, 2090, 2091, 7, 71, 2, 2, 2091, 2092, 7, 84, 2, 2, 2092, 2093, 7, 91, 2, 2, 2093, 2094, 7, 97, 2, 2, 2094, 2095, 7, 85, 2, 2, 2095, 2096, 7, 86, 2, 2, 2096, 2097, 7, 84, 2, 2, 2097, 2098, 7, 75, 2, 2, 2098, 2099, 7, 80, 2, 2, 2099, 2100, 7, 73, 2, 2, 2100, 448, 3, 2, 2, 2, 2101, 2102, 7, 67, 2, 2, 2102, 2103, 7, 78, 2, 2, 2103, 2104, 7, 78, 2, 2, 2104, 2105, 7, 81, 2, 2, 2105, 2106, 7, 89, 2, 2, 2106, 2107, 7, 97, 2, 2, 2107, 2108, 7, 78, 2, 2, 2108, 2109, 7, 71, 2, 2, 2109, 2110, 7, 67, 2, 2, 2110, 2111, 7, 70, 2, 2, 2111, 2112, 7, 75, 2, 2, 2112, 2113, 7, 80, 2, 2, 2113, 2114, 7, 73, 2, 2, 2114, 2115, 7, 97, 2, 2, 2115, 2116, 7, 89, 2, 2, 2116, 2117, 7, 75, 2, 2, 2117, 2118, 7, 78, 2, 2, 2118, 2119, 7, 70, 2, 2, 2119, 2120, 7, 69, 2, 2, 2120, 2121, 7, 67, 2, 2, 2121, 2122, 7, 84, 2, 2, 2122, 2123, 7, 70, 2, 2, 2123, 450, 3, 2, 2, 2, 2124, 2125, 7, 67, 2, 2, 2125, 2126, 7, 80, 2, 2, 2126, 2127, 7, 67, 2, 2, 2127, 2128, 7, 78, 2, 2, 2128, 2129, 7, 91, 2, 2, 2129, 2130, 7, 92, 2, 2, 2130, 2131, 7, 71, 2, 2, 2131, 2132, 7, 97, 2, 2, 2132, 2133, 7, 89, 2, 2, 2133, 2134, 7, 75, 2, 2, 2134, 2135, 7, 78, 2, 2, 2135, 2136, 7, 70, 2, 2, 2136, 2137, 7, 69, 2, 2, 2137, 2138, 7, 67, 2, 2, 2138, 2139, 7, 84, 2, 2, 2139, 2140, 7, 70, 2, 2, 2140, 452, 3, 2, 2, 2, 2141, 2142, 7, 67, 2, 2, 2142, 2143, 7, 80, 2, 2, 2143, 2144, 7, 67, 2, 2, 2144, 2145, 7, 78, 2, 2, 2145, 2146, 7, 91, 2, 2, 2146, 2147, 7, 92, 2, 2, 2147, 2148, 7, 71, 2, 2, 2148, 2149, 7, 84, 2, 2, 2149, 454, 3, 2, 2, 2, 2150, 2151, 7, 67, 2, 2, 2151, 2152, 7, 87, 2, 2, 2152, 2153, 7, 86, 2, 2, 2153, 2154, 7, 81, 2, 2, 2154, 2155, 7, 97, 2, 2, 2155, 2156, 7, 73, 2, 2, 2156, 2157, 7, 71, 2, 2, 2157, 2158, 7, 80, 2, 2, 2158, 2159, 7, 71, 2, 2, 2159, 2160, 7, 84, 2, 2, 2160, 2161, 7, 67, 2, 2, 2161, 2162, 7, 86, 2, 2, 2162, 2163, 7, 71, 2, 2, 2163, 2164, 7, 97, 2, 2, 2164, 2165, 7, 85, 2, 2, 2165, 2166, 7, 91, 2, 2, 2166, 2167, 7, 80, 2, 2, 2167, 2168, 7, 81, 2, 2, 2168, 2169, 7, 80, 2, 2, 2169, 2170, 7, 91, 2, 2, 2170, 2171, 7, 79, 2, 2, 2171, 2172, 7, 85, 2, 2, 2172, 2173, 7, 97, 2, 2, 2173, 2174, 7, 82, 2, 2, 2174, 2175, 7, 74, 2, 2, 2175, 2176, 7, 84, 2, 2, 2176, 2177, 7, 67, 2, 2, 2177, 2178, 7, 85, 2, 2, 2178, 2179, 7, 71, 2, 2, 2179, 2180, 7, 97, 2, 2, 2180, 2181, 7, 83, 2, 2, 2181, 2182, 7, 87, 2, 2, 2182, 2183, 7, 71, 2, 2, 2183, 2184, 7, 84, 2, 2, 2184, 2185, 7, 91, 2, 2, 2185, 456, 3, 2, 2, 2, 2186, 2187, 7, 68, 2, 2, 2187, 2188, 7, 81, 2, 2, 2188, 2189, 7, 81, 2, 2, 2189, 2190, 7, 85, 2, 2, 2190, 2191, 7, 86, 2, 2, 2191, 458, 3, 2, 2, 2, 2192, 2193, 7, 69, 2, 2, 2193, 2194, 7, 87, 2, 2, 2194, 2195, 7, 86, 2, 2, 2195, 2196, 7, 81, 2, 2, 2196, 2197, 7, 72, 2, 2, 2197, 2198, 7, 72, 2, 2, 2198, 2199, 7, 97, 2, 2, 2199, 2200, 7, 72, 2, 2, 2200, 2201, 7, 84, 2, 2, 2201, 2202, 7, 71, 2, 2, 2202, 2203, 7, 83, 2, 2, 2203, 2204, 7, 87, 2, 2, 2204, 2205, 7, 71, 2, 2, 2205, 2206, 7, 80, 2, 2, 2206, 2207, 7, 69, 2, 2, 2207, 2208, 7, 91, 2, 2, 2208, 460, 3, 2, 2, 2, 2209, 2210, 7, 70, 2, 2, 2210, 2211, 7, 71, 2, 2, 2211, 2212, 7, 72, 2, 2, 2212, 2213, 7, 67, 2, 2, 2213, 2214, 7, 87, 2, 2, 2214, 2215, 7, 78, 2, 2, 2215, 2216, 7, 86, 2, 2, 2216, 2217, 7, 97, 2, 2, 2217, 2218, 7, 72, 2, 2, 2218, 2219, 7, 75, 2, 2, 2219, 2220, 7, 71, 2, 2, 2220, 2221, 7, 78, 2, 2, 2221, 2222, 7, 70, 2, 2, 2222, 462, 3, 2, 2, 2, 2223, 2224, 7, 70, 2, 2, 2224, 2225, 7, 71, 2, 2, 2225, 2226, 7, 72, 2, 2, 2226, 2227, 7, 67, 2, 2, 2227, 2228, 7, 87, 2, 2, 2228, 2229, 7, 78, 2, 2, 2229, 2230, 7, 86, 2, 2, 2230, 2231, 7, 97, 2, 2, 2231, 2232, 7, 81, 2, 2, 2232, 2233, 7, 82, 2, 2, 2233, 2234, 7, 71, 2, 2, 2234, 2235, 7, 84, 2, 2, 2235, 2236, 7, 67, 2, 2, 2236, 2237, 7, 86, 2, 2, 2237, 2238, 7, 81, 2, 2, 2238, 2239, 7, 84, 2, 2, 2239, 464, 3, 2, 2, 2, 2240, 2241, 7, 71, 2, 2, 2241, 2242, 7, 80, 2, 2, 2242, 2243, 7, 67, 2, 2, 2243, 2244, 7, 68, 2, 2, 2244, 2245, 7, 78, 2, 2, 2245, 2246, 7, 71, 2, 2, 2246, 2247, 7, 97, 2, 2, 2247, 2248, 7, 82, 2, 2, 2248, 2249, 7, 81, 2, 2, 2249, 2250, 7, 85, 2, 2, 2250, 2251, 7, 75, 2, 2, 2251, 2252, 7, 86, 2, 2, 2252, 2253, 7, 75, 2, 2, 2253, 2254, 7, 81, 2, 2, 2254, 2255, 7, 80, 2, 2, 2255, 2256, 7, 97, 2, 2, 2256, 2257, 7, 75, 2, 2, 2257, 2258, 7, 80, 2, 2, 2258, 2259, 7, 69, 2, 2, 2259, 2260, 7, 84, 2, 2, 2260, 2261, 7, 71, 2, 2, 2261, 2262, 7, 79, 2, 2, 2262, 2263, 7, 71, 2, 2, 2263, 2264, 7, 80, 2, 2, 2264, 2265, 7, 86, 2, 2, 2265, 2266, 7, 85, 2, 2, 2266, 466, 3, 2, 2, 2, 2267, 2268, 7, 72, 2, 2, 2268, 2269, 7, 78, 2, 2, 2269, 2270, 7, 67, 2, 2, 2270, 2271, 7, 73, 2, 2, 2271, 2272, 7, 85, 2, 2, 2272, 468, 3, 2, 2, 2, 2273, 2274, 7, 72, 2, 2, 2274, 2275, 7, 87, 2, 2, 2275, 2276, 7, 92, 2, 2, 2276, 2277, 7, 92, 2, 2, 2277, 2278, 7, 91, 2, 2, 2278, 2279, 7, 97, 2, 2, 2279, 2280, 7, 79, 2, 2, 2280, 2281, 7, 67, 2, 2, 2281, 2282, 7, 90, 2, 2, 2282, 2283, 7, 97, 2, 2, 2283, 2284, 7, 71, 2, 2, 2284, 2285, 7, 90, 2, 2, 2285, 2286, 7, 82, 2, 2, 2286, 2287, 7, 67, 2, 2, 2287, 2288, 7, 80, 2, 2, 2288, 2289, 7, 85, 2, 2, 2289, 2290, 7, 75, 2, 2, 2290, 2291, 7, 81, 2, 2, 2291, 2292, 7, 80, 2, 2, 2292, 2293, 7, 85, 2, 2, 2293, 470, 3, 2, 2, 2, 2294, 2295, 7, 72, 2, 2, 2295, 2296, 7, 87, 2, 2, 2296, 2297, 7, 92, 2, 2, 2297, 2298, 7, 92, 2, 2, 2298, 2299, 7, 91, 2, 2, 2299, 2300, 7, 97, 2, 2, 2300, 2301, 7, 82, 2, 2, 2301, 2302, 7, 84, 2, 2, 2302, 2303, 7, 71, 2, 2, 2303, 2304, 7, 72, 2, 2, 2304, 2305, 7, 75, 2, 2, 2305, 2306, 7, 90, 2, 2, 2306, 2307, 7, 97, 2, 2, 2307, 2308, 7, 78, 2, 2, 2308, 2309, 7, 71, 2, 2, 2309, 2310, 7, 80, 2, 2, 2310, 2311, 7, 73, 2, 2, 2311, 2312, 7, 86, 2, 2, 2312, 2313, 7, 74, 2, 2, 2313, 472, 3, 2, 2, 2, 2314, 2315, 7, 72, 2, 2, 2315, 2316, 7, 87, 2, 2, 2316, 2317, 7, 92, 2, 2, 2317, 2318, 7, 92, 2, 2, 2318, 2319, 7, 91, 2, 2, 2319, 2320, 7, 97, 2, 2, 2320, 2321, 7, 86, 2, 2, 2321, 2322, 7, 84, 2, 2, 2322, 2323, 7, 67, 2, 2, 2323, 2324, 7, 80, 2, 2, 2324, 2325, 7, 85, 2, 2, 2325, 2326, 7, 82, 2, 2, 2326, 2327, 7, 81, 2, 2, 2327, 2328, 7, 85, 2, 2, 2328, 2329, 7, 75, 2, 2, 2329, 2330, 7, 86, 2, 2, 2330, 2331, 7, 75, 2, 2, 2331, 2332, 7, 81, 2, 2, 2332, 2333, 7, 80, 2, 2, 2333, 2334, 7, 85, 2, 2, 2334, 474, 3, 2, 2, 2, 2335, 2336, 7, 72, 2, 2, 2336, 2337, 7, 87, 2, 2, 2337, 2338, 7, 92, 2, 2, 2338, 2339, 7, 92, 2, 2, 2339, 2340, 7, 91, 2, 2, 2340, 2341, 7, 97, 2, 2, 2341, 2342, 7, 84, 2, 2, 2342, 2343, 7, 71, 2, 2, 2343, 2344, 7, 89, 2, 2, 2344, 2345, 7, 84, 2, 2, 2345, 2346, 7, 75, 2, 2, 2346, 2347, 7, 86, 2, 2, 2347, 2348, 7, 71, 2, 2, 2348, 476, 3, 2, 2, 2, 2349, 2350, 7, 72, 2, 2, 2350, 2351, 7, 87, 2, 2, 2351, 2352, 7, 92, 2, 2, 2352, 2353, 7, 92, 2, 2, 2353, 2354, 7, 75, 2, 2, 2354, 2355, 7, 80, 2, 2, 2355, 2356, 7, 71, 2, 2, 2356, 2357, 7, 85, 2, 2, 2357, 2358, 7, 85, 2, 2, 2358, 478, 3, 2, 2, 2, 2359, 2360, 7, 78, 2, 2, 2360, 2361, 7, 71, 2, 2, 2361, 2362, 7, 80, 2, 2, 2362, 2363, 7, 75, 2, 2, 2363, 2364, 7, 71, 2, 2, 2364, 2365, 7, 80, 2, 2, 2365, 2366, 7, 86, 2, 2, 2366, 480, 3, 2, 2, 2, 2367, 2368, 7, 78, 2, 2, 2368, 2369, 7, 81, 2, 2, 2369, 2370, 7, 89, 2, 2, 2370, 2371, 7, 97, 2, 2, 2371, 2372, 7, 72, 2, 2, 2372, 2373, 7, 84, 2, 2, 2373, 2374, 7, 71, 2, 2, 2374, 2375, 7, 83, 2, 2, 2375, 2376, 7, 97, 2, 2, 2376, 2377, 7, 81, 2, 2, 2377, 2378, 7, 82, 2, 2, 2378, 2379, 7, 71, 2, 2, 2379, 2380, 7, 84, 2, 2, 2380, 2381, 7, 67, 2, 2, 2381, 2382, 7, 86, 2, 2, 2382, 2383, 7, 81, 2, 2, 2383, 2384, 7, 84, 2, 2, 2384, 482, 3, 2, 2, 2, 2385, 2386, 7, 79, 2, 2, 2386, 2387, 7, 67, 2, 2, 2387, 2388, 7, 90, 2, 2, 2388, 2389, 7, 97, 2, 2, 2389, 2390, 7, 70, 2, 2, 2390, 2391, 7, 71, 2, 2, 2391, 2392, 7, 86, 2, 2, 2392, 2393, 7, 71, 2, 2, 2393, 2394, 7, 84, 2, 2, 2394, 2395, 7, 79, 2, 2, 2395, 2396, 7, 75, 2, 2, 2396, 2397, 7, 80, 2, 2, 2397, 2398, 7, 75, 2, 2, 2398, 2399, 7, 92, 2, 2, 2399, 2400, 7, 71, 2, 2, 2400, 2401, 7, 70, 2, 2, 2401, 2402, 7, 97, 2, 2, 2402, 2403, 7, 85, 2, 2, 2403, 2404, 7, 86, 2, 2, 2404, 2405, 7, 67, 2, 2, 2405, 2406, 7, 86, 2, 2, 2406, 2407, 7, 71, 2, 2, 2407, 2408, 7, 85, 2, 2, 2408, 484, 3, 2, 2, 2, 2409, 2410, 7, 79, 2, 2, 2410, 2411, 7, 67, 2, 2, 2411, 2412, 7, 90, 2, 2, 2412, 2413, 7, 97, 2, 2, 2413, 2414, 7, 71, 2, 2, 2414, 2415, 7, 90, 2, 2, 2415, 2416, 7, 82, 2, 2, 2416, 2417, 7, 67, 2, 2, 2417, 2418, 7, 80, 2, 2, 2418, 2419, 7, 85, 2, 2, 2419, 2420, 7, 75, 2, 2, 2420, 2421, 7, 81, 2, 2, 2421, 2422, 7, 80, 2, 2, 2422, 2423, 7, 85, 2, 2, 2423, 486, 3, 2, 2, 2, 2424, 2425, 7, 79, 2, 2, 2425, 2426, 7, 75, 2, 2, 2426, 2427, 7, 80, 2, 2, 2427, 2428, 7, 75, 2, 2, 2428, 2429, 7, 79, 2, 2, 2429, 2430, 7, 87, 2, 2, 2430, 2431, 7, 79, 2, 2, 2431, 2432, 7, 97, 2, 2, 2432, 2433, 7, 85, 2, 2, 2433, 2434, 7, 74, 2, 2, 2434, 2435, 7, 81, 2, 2, 2435, 2436, 7, 87, 2, 2, 2436, 2437, 7, 78, 2, 2, 2437, 2438, 7, 70, 2, 2, 2438, 2439, 7, 97, 2, 2, 2439, 2440, 7, 79, 2, 2, 2440, 2441, 7, 67, 2, 2, 2441, 2442, 7, 86, 2, 2, 2442, 2443, 7, 69, 2, 2, 2443, 2444, 7, 74, 2, 2, 2444, 488, 3, 2, 2, 2, 2445, 2446, 7, 81, 2, 2, 2446, 2447, 7, 82, 2, 2, 2447, 2448, 7, 71, 2, 2, 2448, 2449, 7, 84, 2, 2, 2449, 2450, 7, 67, 2, 2, 2450, 2451, 7, 86, 2, 2, 2451, 2452, 7, 81, 2, 2, 2452, 2453, 7, 84, 2, 2, 2453, 490, 3, 2, 2, 2, 2454, 2455, 7, 82, 2, 2, 2455, 2456, 7, 74, 2, 2, 2456, 2457, 7, 84, 2, 2, 2457, 2458, 7, 67, 2, 2, 2458, 2459, 7, 85, 2, 2, 2459, 2460, 7, 71, 2, 2, 2460, 2461, 7, 97, 2, 2, 2461, 2462, 7, 85, 2, 2, 2462, 2463, 7, 78, 2, 2, 2463, 2464, 7, 81, 2, 2, 2464, 2465, 7, 82, 2, 2, 2465, 492, 3, 2, 2, 2, 2466, 2467, 7, 82, 2, 2, 2467, 2468, 7, 84, 2, 2, 2468, 2469, 7, 71, 2, 2, 2469, 2470, 7, 72, 2, 2, 2470, 2471, 7, 75, 2, 2, 2471, 2472, 7, 90, 2, 2, 2472, 2473, 7, 97, 2, 2, 2473, 2474, 7, 78, 2, 2, 2474, 2475, 7, 71, 2, 2, 2475, 2476, 7, 80, 2, 2, 2476, 2477, 7, 73, 2, 2, 2477, 2478, 7, 86, 2, 2, 2478, 2479, 7, 74, 2, 2, 2479, 494, 3, 2, 2, 2, 2480, 2481, 7, 83, 2, 2, 2481, 2482, 7, 87, 2, 2, 2482, 2483, 7, 81, 2, 2, 2483, 2484, 7, 86, 2, 2, 2484, 2485, 7, 71, 2, 2, 2485, 2486, 7, 97, 2, 2, 2486, 2487, 7, 67, 2, 2, 2487, 2488, 7, 80, 2, 2, 2488, 2489, 7, 67, 2, 2, 2489, 2490, 7, 78, 2, 2, 2490, 2491, 7, 91, 2, 2, 2491, 2492, 7, 92, 2, 2, 2492, 2493, 7, 71, 2, 2, 2493, 2494, 7, 84, 2, 2, 2494, 496, 3, 2, 2, 2, 2495, 2496, 7, 83, 2, 2, 2496, 2497, 7, 87, 2, 2, 2497, 2498, 7, 81, 2, 2, 2498, 2499, 7, 86, 2, 2, 2499, 2500, 7, 71, 2, 2, 2500, 2501, 7, 97, 2, 2, 2501, 2502, 7, 72, 2, 2, 2502, 2503, 7, 75, 2, 2, 2503, 2504, 7, 71, 2, 2, 2504, 2505, 7, 78, 2, 2, 2505, 2506, 7, 70, 2, 2, 2506, 2507, 7, 97, 2, 2, 2507, 2508, 7, 85, 2, 2, 2508, 2509, 7, 87, 2, 2, 2509, 2510, 7, 72, 2, 2, 2510, 2511, 7, 72, 2, 2, 2511, 2512, 7, 75, 2, 2, 2512, 2513, 7, 90, 2, 2, 2513, 498, 3, 2, 2, 2, 2514, 2515, 7, 84, 2, 2, 2515, 2516, 7, 71, 2, 2, 2516, 2517, 7, 89, 2, 2, 2517, 2518, 7, 84, 2, 2, 2518, 2519, 7, 75, 2, 2, 2519, 2520, 7, 86, 2, 2, 2520, 2521, 7, 71, 2, 2, 2521, 500, 3, 2, 2, 2, 2522, 2523, 7, 85, 2, 2, 2523, 2524, 7, 78, 2, 2, 2524, 2525, 7, 81, 2, 2, 2525, 2526, 7, 82, 2, 2, 2526, 502, 3, 2, 2, 2, 2527, 2528, 7, 86, 2, 2, 2528, 2529, 7, 75, 2, 2, 2529, 2530, 7, 71, 2, 2, 2530, 2531, 7, 97, 2, 2, 2531, 2532, 7, 68, 2, 2, 2532, 2533, 7, 84, 2, 2, 2533, 2534, 7, 71, 2, 2, 2534, 2535, 7, 67, 2, 2, 2535, 2536, 7, 77, 2, 2, 2536, 2537, 7, 71, 2, 2, 2537, 2538, 7, 84, 2, 2, 2538, 504, 3, 2, 2, 2, 2539, 2540, 7, 86, 2, 2, 2540, 2541, 7, 91, 2, 2, 2541, 2542, 7, 82, 2, 2, 2542, 2543, 7, 71, 2, 2, 2543, 506, 3, 2, 2, 2, 2544, 2545, 7, 92, 2, 2, 2545, 2546, 7, 71, 2, 2, 2546, 2547, 7, 84, 2, 2, 2547, 2548, 7, 81, 2, 2, 2548, 2549, 7, 97, 2, 2, 2549, 2550, 7, 86, 2, 2, 2550, 2551, 7, 71, 2, 2, 2551, 2552, 7, 84, 2, 2, 2552, 2553, 7, 79, 2, 2, 2553, 2554, 7, 85, 2, 2, 2554, 2555, 7, 97, 2, 2, 2555, 2556, 7, 83, 2, 2, 2556, 2557, 7, 87, 2, 2, 2557, 2558, 7, 71, 2, 2, 2558, 2559, 7, 84, 2, 2, 2559, 2560, 7, 91, 2, 2, 2560, 508, 3, 2, 2, 2, 2561, 2562, 7, 85, 2, 2, 2562, 2563, 7, 82, 2, 2, 2563, 2564, 7, 67, 2, 2, 2564, 2565, 7, 80, 2, 2, 2565, 510, 3, 2, 2, 2, 2566, 2567, 7, 79, 2, 2, 2567, 2568, 7, 85, 2, 2, 2568, 512, 3, 2, 2, 2, 2569, 2570, 7, 85, 2, 2, 2570, 514, 3, 2, 2, 2, 2571, 2572, 7, 79, 2, 2, 2572, 516, 3, 2, 2, 2, 2573, 2574, 7, 74, 2, 2, 2574, 518, 3, 2, 2, 2, 2575, 2576, 7, 89, 2, 2, 2576, 520, 3, 2, 2, 2, 2577, 2578, 7, 83, 2, 2, 2578, 522, 3, 2, 2, 2, 2579, 2580, 7, 91, 2, 2, 2580, 524, 3, 2, 2, 2, 2581, 2582, 5, 533, 267, 2, 2582, 526, 3, 2, 2, 2, 2583, 2585, 5, 543, 272, 2, 2584, 2583, 3, 2, 2, 2, 2585, 2586, 3, 2, 2, 2, 2586, 2584, 3, 2, 2, 2, 2586, 2587, 3, 2, 2, 2, 2587, 528, 3, 2, 2, 2, 2588, 2590, 5, 543, 272, 2, 2589, 2588, 3, 2, 2, 2, 2590, 2591, 3, 2, 2, 2, 2591, 2589, 3, 2, 2, 2, 2591, 2592, 3, 2, 2, 2, 2592, 2594, 3, 2, 2, 2, 2593, 2589, 3, 2, 2, 2, 2593, 2594, 3, 2, 2, 2, 2594, 2595, 3, 2, 2, 2, 2595, 2597, 7, 48, 2, 2, 2596, 2598, 5, 543, 272, 2, 2597, 2596, 3, 2, 2, 2, 2598, 2599, 3, 2, 2, 2, 2599, 2597, 3, 2, 2, 2, 2599, 2600, 3, 2, 2, 2, 2600, 530, 3, 2, 2, 2, 2601, 2603, 9, 2, 2, 2, 2602, 2604, 9, 3, 2, 2, 2603, 2602, 3, 2, 2, 2, 2604, 2605, 3, 2, 2, 2, 2605, 2603, 3, 2, 2, 2, 2605, 2606, 3, 2, 2, 2, 2606, 2608, 3, 2, 2, 2, 2607, 2601, 3, 2, 2, 2, 2608, 2611, 3, 2, 2, 2, 2609, 2607, 3, 2, 2, 2, 2609, 2610, 3, 2, 2, 2, 2610, 532, 3, 2, 2, 2, 2611, 2609, 3, 2, 2, 2, 2612, 2614, 9, 4, 2, 2, 2613, 2612, 3, 2, 2, 2, 2614, 2615, 3, 2, 2, 2, 2615, 2616, 3, 2, 2, 2, 2615, 2613, 3, 2, 2, 2, 2616, 2620, 3, 2, 2, 2, 2617, 2619, 9, 5, 2, 2, 2618, 2617, 3, 2, 2, 2, 2619, 2622, 3, 2, 2, 2, 2620, 2618, 3, 2, 2, 2, 2620, 2621, 3, 2, 2, 2, 2621, 534, 3, 2, 2, 2, 2622, 2620, 3, 2, 2, 2, 2623, 2624, 5, 533, 267, 2, 2624, 2625, 5, 531, 266, 2, 2625, 536, 3, 2, 2, 2, 2626, 2634, 7, 36, 2, 2, 2627, 2628, 7, 94, 2, 2, 2628, 2633, 11, 2, 2, 2, 2629, 2630, 7, 36, 2, 2, 2630, 2633, 7, 36, 2, 2, 2631, 2633, 10, 6, 2, 2, 2632, 2627, 3, 2, 2, 2, 2632, 2629, 3, 2, 2, 2, 2632, 2631, 3, 2, 2, 2, 2633, 2636, 3, 2, 2, 2, 2634, 2632, 3, 2, 2, 2, 2634, 2635, 3, 2, 2, 2, 2635, 2637, 3, 2, 2, 2, 2636, 2634, 3, 2, 2, 2, 2637, 2638, 7, 36, 2, 2, 2638, 538, 3, 2, 2, 2, 2639, 2647, 7, 41, 2, 2, 2640, 2641, 7, 94, 2, 2, 2641, 2646, 11, 2, 2, 2, 2642, 2643, 7, 41, 2, 2, 2643, 2646, 7, 41, 2, 2, 2644, 2646, 10, 7, 2, 2, 2645, 2640, 3, 2, 2, 2, 2645, 2642, 3, 2, 2, 2, 2645, 2644, 3, 2, 2, 2, 2646, 2649, 3, 2, 2, 2, 2647, 2645, 3, 2, 2, 2, 2647, 2648, 3, 2, 2, 2, 2648, 2650, 3, 2, 2, 2, 2649, 2647, 3, 2, 2, 2, 2650, 2651, 7, 41, 2, 2, 2651, 540, 3, 2, 2, 2, 2652, 2660, 7, 98, 2, 2, 2653, 2654, 7, 94, 2, 2, 2654, 2659, 11, 2, 2, 2, 2655, 2656, 7, 98, 2, 2, 2656, 2659, 7, 98, 2, 2, 2657, 2659, 10, 8, 2, 2, 2658, 2653, 3, 2, 2, 2, 2658, 2655, 3, 2, 2, 2, 2658, 2657, 3, 2, 2, 2, 2659, 2662, 3, 2, 2, 2, 2660, 2658, 3, 2, 2, 2, 2660, 2661, 3, 2, 2, 2, 2661, 2663, 3, 2, 2, 2, 2662, 2660, 3, 2, 2, 2, 2663, 2664, 7, 98, 2, 2, 2664, 542, 3, 2, 2, 2, 2665, 2666, 9, 9, 2, 2, 2666, 544, 3, 2, 2, 2, 2667, 2668, 11, 2, 2, 2, 2668, 2669, 3, 2, 2, 2, 2669, 2670, 8, 273, 2, 2, 2670, 546, 3, 2, 2, 2, 17, 2, 2586, 2591, 2593, 2599, 2605, 2609, 2615, 2620, 2632, 2634, 2645, 2647, 2658, 2660, 3, 2, 5, 2] \ No newline at end of file diff --git a/dashboards-observability/common/query_manager/antlr/grammar/.antlr/OpenSearchPPLLexer.java b/dashboards-observability/common/query_manager/antlr/grammar/.antlr/OpenSearchPPLLexer.java new file mode 100644 index 000000000..b7cc88a4e --- /dev/null +++ b/dashboards-observability/common/query_manager/antlr/grammar/.antlr/OpenSearchPPLLexer.java @@ -0,0 +1,1277 @@ +// Generated from /Users/menwe/amazon/OpenSearch-Dashboards/plugins/dashboards-observability/common/query_manager/antlr/grammar/OpenSearchPPLLexer.g4 by ANTLR 4.9.2 +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.TokenStream; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.misc.*; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class OpenSearchPPLLexer extends Lexer { + static { RuntimeMetaData.checkVersion("4.9.2", RuntimeMetaData.VERSION); } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + SEARCH=1, FROM=2, WHERE=3, FIELDS=4, RENAME=5, STATS=6, DEDUP=7, SORT=8, + EVAL=9, HEAD=10, TOP=11, RARE=12, PARSE=13, KMEANS=14, AD=15, AS=16, BY=17, + SOURCE=18, INDEX=19, D=20, DESC=21, SORTBY=22, AUTO=23, STR=24, IP=25, + NUM=26, KEEPEMPTY=27, CONSECUTIVE=28, DEDUP_SPLITVALUES=29, PARTITIONS=30, + ALLNUM=31, DELIM=32, CENTROIDS=33, ITERATIONS=34, DISTANCE_TYPE=35, NUMBER_OF_TREES=36, + SHINGLE_SIZE=37, SAMPLE_SIZE=38, OUTPUT_AFTER=39, TIME_DECAY=40, ANOMALY_RATE=41, + TIME_FIELD=42, TIME_ZONE=43, TRAINING_DATA_SIZE=44, ANOMALY_SCORE_THRESHOLD=45, + CASE=46, IN=47, NOT=48, OR=49, AND=50, XOR=51, TRUE=52, FALSE=53, REGEXP=54, + DATETIME=55, INTERVAL=56, MICROSECOND=57, MILLISECOND=58, SECOND=59, MINUTE=60, + HOUR=61, DAY=62, WEEK=63, MONTH=64, QUARTER=65, YEAR=66, SECOND_MICROSECOND=67, + MINUTE_MICROSECOND=68, MINUTE_SECOND=69, HOUR_MICROSECOND=70, HOUR_SECOND=71, + HOUR_MINUTE=72, DAY_MICROSECOND=73, DAY_SECOND=74, DAY_MINUTE=75, DAY_HOUR=76, + YEAR_MONTH=77, DATAMODEL=78, LOOKUP=79, SAVEDSEARCH=80, INT=81, INTEGER=82, + DOUBLE=83, LONG=84, FLOAT=85, STRING=86, BOOLEAN=87, PIPE=88, COMMA=89, + DOT=90, EQUAL=91, GREATER=92, LESS=93, NOT_GREATER=94, NOT_LESS=95, NOT_EQUAL=96, + PLUS=97, MINUS=98, STAR=99, DIVIDE=100, MODULE=101, EXCLAMATION_SYMBOL=102, + COLON=103, LT_PRTHS=104, RT_PRTHS=105, LT_SQR_PRTHS=106, RT_SQR_PRTHS=107, + SINGLE_QUOTE=108, DOUBLE_QUOTE=109, BACKTICK=110, BIT_NOT_OP=111, BIT_AND_OP=112, + BIT_XOR_OP=113, AVG=114, COUNT=115, DISTINCT_COUNT=116, ESTDC=117, ESTDC_ERROR=118, + MAX=119, MEAN=120, MEDIAN=121, MIN=122, MODE=123, RANGE=124, STDEV=125, + STDEVP=126, SUM=127, SUMSQ=128, VAR_SAMP=129, VAR_POP=130, STDDEV_SAMP=131, + STDDEV_POP=132, PERCENTILE=133, FIRST=134, LAST=135, LIST=136, VALUES=137, + EARLIEST=138, EARLIEST_TIME=139, LATEST=140, LATEST_TIME=141, PER_DAY=142, + PER_HOUR=143, PER_MINUTE=144, PER_SECOND=145, RATE=146, SPARKLINE=147, + C=148, DC=149, ABS=150, CEIL=151, CEILING=152, CONV=153, CRC32=154, E=155, + EXP=156, FLOOR=157, LN=158, LOG=159, LOG10=160, LOG2=161, MOD=162, PI=163, + POW=164, POWER=165, RAND=166, ROUND=167, SIGN=168, SQRT=169, TRUNCATE=170, + ACOS=171, ASIN=172, ATAN=173, ATAN2=174, COS=175, COT=176, DEGREES=177, + RADIANS=178, SIN=179, TAN=180, ADDDATE=181, DATE=182, DATE_ADD=183, DATE_SUB=184, + DAYOFMONTH=185, DAYOFWEEK=186, DAYOFYEAR=187, DAYNAME=188, FROM_DAYS=189, + MONTHNAME=190, SUBDATE=191, TIME=192, TIME_TO_SEC=193, TIMESTAMP=194, + DATE_FORMAT=195, TO_DAYS=196, SUBSTR=197, SUBSTRING=198, LTRIM=199, RTRIM=200, + TRIM=201, TO=202, LOWER=203, UPPER=204, CONCAT=205, CONCAT_WS=206, LENGTH=207, + STRCMP=208, RIGHT=209, LEFT=210, ASCII=211, LOCATE=212, REPLACE=213, CAST=214, + LIKE=215, ISNULL=216, ISNOTNULL=217, IFNULL=218, NULLIF=219, IF=220, MATCH=221, + MATCH_PHRASE=222, SIMPLE_QUERY_STRING=223, ALLOW_LEADING_WILDCARD=224, + ANALYZE_WILDCARD=225, ANALYZER=226, AUTO_GENERATE_SYNONYMS_PHRASE_QUERY=227, + BOOST=228, CUTOFF_FREQUENCY=229, DEFAULT_FIELD=230, DEFAULT_OPERATOR=231, + ENABLE_POSITION_INCREMENTS=232, FLAGS=233, FUZZY_MAX_EXPANSIONS=234, FUZZY_PREFIX_LENGTH=235, + FUZZY_TRANSPOSITIONS=236, FUZZY_REWRITE=237, FUZZINESS=238, LENIENT=239, + LOW_FREQ_OPERATOR=240, MAX_DETERMINIZED_STATES=241, MAX_EXPANSIONS=242, + MINIMUM_SHOULD_MATCH=243, OPERATOR=244, PHRASE_SLOP=245, PREFIX_LENGTH=246, + QUOTE_ANALYZER=247, QUOTE_FIELD_SUFFIX=248, REWRITE=249, SLOP=250, TIE_BREAKER=251, + TYPE=252, ZERO_TERMS_QUERY=253, SPAN=254, MS=255, S=256, M=257, H=258, + W=259, Q=260, Y=261, ID=262, INTEGER_LITERAL=263, DECIMAL_LITERAL=264, + ID_DATE_SUFFIX=265, DQUOTA_STRING=266, SQUOTA_STRING=267, BQUOTA_STRING=268, + ERROR_RECOGNITION=269; + public static final int + WHITESPACE=2, ERRORCHANNEL=3; + public static String[] channelNames = { + "DEFAULT_TOKEN_CHANNEL", "HIDDEN", "WHITESPACE", "ERRORCHANNEL" + }; + + public static String[] modeNames = { + "DEFAULT_MODE" + }; + + private static String[] makeRuleNames() { + return new String[] { + "SEARCH", "FROM", "WHERE", "FIELDS", "RENAME", "STATS", "DEDUP", "SORT", + "EVAL", "HEAD", "TOP", "RARE", "PARSE", "KMEANS", "AD", "AS", "BY", "SOURCE", + "INDEX", "D", "DESC", "SORTBY", "AUTO", "STR", "IP", "NUM", "KEEPEMPTY", + "CONSECUTIVE", "DEDUP_SPLITVALUES", "PARTITIONS", "ALLNUM", "DELIM", + "CENTROIDS", "ITERATIONS", "DISTANCE_TYPE", "NUMBER_OF_TREES", "SHINGLE_SIZE", + "SAMPLE_SIZE", "OUTPUT_AFTER", "TIME_DECAY", "ANOMALY_RATE", "TIME_FIELD", + "TIME_ZONE", "TRAINING_DATA_SIZE", "ANOMALY_SCORE_THRESHOLD", "CASE", + "IN", "NOT", "OR", "AND", "XOR", "TRUE", "FALSE", "REGEXP", "DATETIME", + "INTERVAL", "MICROSECOND", "MILLISECOND", "SECOND", "MINUTE", "HOUR", + "DAY", "WEEK", "MONTH", "QUARTER", "YEAR", "SECOND_MICROSECOND", "MINUTE_MICROSECOND", + "MINUTE_SECOND", "HOUR_MICROSECOND", "HOUR_SECOND", "HOUR_MINUTE", "DAY_MICROSECOND", + "DAY_SECOND", "DAY_MINUTE", "DAY_HOUR", "YEAR_MONTH", "DATAMODEL", "LOOKUP", + "SAVEDSEARCH", "INT", "INTEGER", "DOUBLE", "LONG", "FLOAT", "STRING", + "BOOLEAN", "PIPE", "COMMA", "DOT", "EQUAL", "GREATER", "LESS", "NOT_GREATER", + "NOT_LESS", "NOT_EQUAL", "PLUS", "MINUS", "STAR", "DIVIDE", "MODULE", + "EXCLAMATION_SYMBOL", "COLON", "LT_PRTHS", "RT_PRTHS", "LT_SQR_PRTHS", + "RT_SQR_PRTHS", "SINGLE_QUOTE", "DOUBLE_QUOTE", "BACKTICK", "BIT_NOT_OP", + "BIT_AND_OP", "BIT_XOR_OP", "AVG", "COUNT", "DISTINCT_COUNT", "ESTDC", + "ESTDC_ERROR", "MAX", "MEAN", "MEDIAN", "MIN", "MODE", "RANGE", "STDEV", + "STDEVP", "SUM", "SUMSQ", "VAR_SAMP", "VAR_POP", "STDDEV_SAMP", "STDDEV_POP", + "PERCENTILE", "FIRST", "LAST", "LIST", "VALUES", "EARLIEST", "EARLIEST_TIME", + "LATEST", "LATEST_TIME", "PER_DAY", "PER_HOUR", "PER_MINUTE", "PER_SECOND", + "RATE", "SPARKLINE", "C", "DC", "ABS", "CEIL", "CEILING", "CONV", "CRC32", + "E", "EXP", "FLOOR", "LN", "LOG", "LOG10", "LOG2", "MOD", "PI", "POW", + "POWER", "RAND", "ROUND", "SIGN", "SQRT", "TRUNCATE", "ACOS", "ASIN", + "ATAN", "ATAN2", "COS", "COT", "DEGREES", "RADIANS", "SIN", "TAN", "ADDDATE", + "DATE", "DATE_ADD", "DATE_SUB", "DAYOFMONTH", "DAYOFWEEK", "DAYOFYEAR", + "DAYNAME", "FROM_DAYS", "MONTHNAME", "SUBDATE", "TIME", "TIME_TO_SEC", + "TIMESTAMP", "DATE_FORMAT", "TO_DAYS", "SUBSTR", "SUBSTRING", "LTRIM", + "RTRIM", "TRIM", "TO", "LOWER", "UPPER", "CONCAT", "CONCAT_WS", "LENGTH", + "STRCMP", "RIGHT", "LEFT", "ASCII", "LOCATE", "REPLACE", "CAST", "LIKE", + "ISNULL", "ISNOTNULL", "IFNULL", "NULLIF", "IF", "MATCH", "MATCH_PHRASE", + "SIMPLE_QUERY_STRING", "ALLOW_LEADING_WILDCARD", "ANALYZE_WILDCARD", + "ANALYZER", "AUTO_GENERATE_SYNONYMS_PHRASE_QUERY", "BOOST", "CUTOFF_FREQUENCY", + "DEFAULT_FIELD", "DEFAULT_OPERATOR", "ENABLE_POSITION_INCREMENTS", "FLAGS", + "FUZZY_MAX_EXPANSIONS", "FUZZY_PREFIX_LENGTH", "FUZZY_TRANSPOSITIONS", + "FUZZY_REWRITE", "FUZZINESS", "LENIENT", "LOW_FREQ_OPERATOR", "MAX_DETERMINIZED_STATES", + "MAX_EXPANSIONS", "MINIMUM_SHOULD_MATCH", "OPERATOR", "PHRASE_SLOP", + "PREFIX_LENGTH", "QUOTE_ANALYZER", "QUOTE_FIELD_SUFFIX", "REWRITE", "SLOP", + "TIE_BREAKER", "TYPE", "ZERO_TERMS_QUERY", "SPAN", "MS", "S", "M", "H", + "W", "Q", "Y", "ID", "INTEGER_LITERAL", "DECIMAL_LITERAL", "DATE_SUFFIX", + "ID_LITERAL", "ID_DATE_SUFFIX", "DQUOTA_STRING", "SQUOTA_STRING", "BQUOTA_STRING", + "DEC_DIGIT", "ERROR_RECOGNITION" + }; + } + public static final String[] ruleNames = makeRuleNames(); + + private static String[] makeLiteralNames() { + return new String[] { + null, "'SEARCH'", "'FROM'", "'WHERE'", "'FIELDS'", "'RENAME'", "'STATS'", + "'DEDUP'", "'SORT'", "'EVAL'", "'HEAD'", "'TOP'", "'RARE'", "'PARSE'", + "'KMEANS'", "'AD'", "'AS'", "'BY'", "'SOURCE'", "'INDEX'", "'D'", "'DESC'", + "'SORTBY'", "'AUTO'", "'STR'", "'IP'", "'NUM'", "'KEEPEMPTY'", "'CONSECUTIVE'", + "'DEDUP_SPLITVALUES'", "'PARTITIONS'", "'ALLNUM'", "'DELIM'", "'CENTROIDS'", + "'ITERATIONS'", "'DISTANCE_TYPE'", "'NUMBER_OF_TREES'", "'SHINGLE_SIZE'", + "'SAMPLE_SIZE'", "'OUTPUT_AFTER'", "'TIME_DECAY'", "'ANOMALY_RATE'", + "'TIME_FIELD'", "'TIME_ZONE'", "'TRAINING_DATA_SIZE'", "'ANOMALY_SCORE_THRESHOLD'", + "'CASE'", "'IN'", "'NOT'", "'OR'", "'AND'", "'XOR'", "'TRUE'", "'FALSE'", + "'REGEXP'", "'DATETIME'", "'INTERVAL'", "'MICROSECOND'", "'MILLISECOND'", + "'SECOND'", "'MINUTE'", "'HOUR'", "'DAY'", "'WEEK'", "'MONTH'", "'QUARTER'", + "'YEAR'", "'SECOND_MICROSECOND'", "'MINUTE_MICROSECOND'", "'MINUTE_SECOND'", + "'HOUR_MICROSECOND'", "'HOUR_SECOND'", "'HOUR_MINUTE'", "'DAY_MICROSECOND'", + "'DAY_SECOND'", "'DAY_MINUTE'", "'DAY_HOUR'", "'YEAR_MONTH'", "'DATAMODEL'", + "'LOOKUP'", "'SAVEDSEARCH'", "'INT'", "'INTEGER'", "'DOUBLE'", "'LONG'", + "'FLOAT'", "'STRING'", "'BOOLEAN'", "'|'", "','", "'.'", "'='", "'>'", + "'<'", null, null, null, "'+'", "'-'", "'*'", "'/'", "'%'", "'!'", "':'", + "'('", "')'", "'['", "']'", "'''", "'\"'", "'`'", "'~'", "'&'", "'^'", + "'AVG'", "'COUNT'", "'DISTINCT_COUNT'", "'ESTDC'", "'ESTDC_ERROR'", "'MAX'", + "'MEAN'", "'MEDIAN'", "'MIN'", "'MODE'", "'RANGE'", "'STDEV'", "'STDEVP'", + "'SUM'", "'SUMSQ'", "'VAR_SAMP'", "'VAR_POP'", "'STDDEV_SAMP'", "'STDDEV_POP'", + "'PERCENTILE'", "'FIRST'", "'LAST'", "'LIST'", "'VALUES'", "'EARLIEST'", + "'EARLIEST_TIME'", "'LATEST'", "'LATEST_TIME'", "'PER_DAY'", "'PER_HOUR'", + "'PER_MINUTE'", "'PER_SECOND'", "'RATE'", "'SPARKLINE'", "'C'", "'DC'", + "'ABS'", "'CEIL'", "'CEILING'", "'CONV'", "'CRC32'", "'E'", "'EXP'", + "'FLOOR'", "'LN'", "'LOG'", "'LOG10'", "'LOG2'", "'MOD'", "'PI'", "'POW'", + "'POWER'", "'RAND'", "'ROUND'", "'SIGN'", "'SQRT'", "'TRUNCATE'", "'ACOS'", + "'ASIN'", "'ATAN'", "'ATAN2'", "'COS'", "'COT'", "'DEGREES'", "'RADIANS'", + "'SIN'", "'TAN'", "'ADDDATE'", "'DATE'", "'DATE_ADD'", "'DATE_SUB'", + "'DAYOFMONTH'", "'DAYOFWEEK'", "'DAYOFYEAR'", "'DAYNAME'", "'FROM_DAYS'", + "'MONTHNAME'", "'SUBDATE'", "'TIME'", "'TIME_TO_SEC'", "'TIMESTAMP'", + "'DATE_FORMAT'", "'TO_DAYS'", "'SUBSTR'", "'SUBSTRING'", "'LTRIM'", "'RTRIM'", + "'TRIM'", "'TO'", "'LOWER'", "'UPPER'", "'CONCAT'", "'CONCAT_WS'", "'LENGTH'", + "'STRCMP'", "'RIGHT'", "'LEFT'", "'ASCII'", "'LOCATE'", "'REPLACE'", + "'CAST'", "'LIKE'", "'ISNULL'", "'ISNOTNULL'", "'IFNULL'", "'NULLIF'", + "'IF'", "'MATCH'", "'MATCH_PHRASE'", "'SIMPLE_QUERY_STRING'", "'ALLOW_LEADING_WILDCARD'", + "'ANALYZE_WILDCARD'", "'ANALYZER'", "'AUTO_GENERATE_SYNONYMS_PHRASE_QUERY'", + "'BOOST'", "'CUTOFF_FREQUENCY'", "'DEFAULT_FIELD'", "'DEFAULT_OPERATOR'", + "'ENABLE_POSITION_INCREMENTS'", "'FLAGS'", "'FUZZY_MAX_EXPANSIONS'", + "'FUZZY_PREFIX_LENGTH'", "'FUZZY_TRANSPOSITIONS'", "'FUZZY_REWRITE'", + "'FUZZINESS'", "'LENIENT'", "'LOW_FREQ_OPERATOR'", "'MAX_DETERMINIZED_STATES'", + "'MAX_EXPANSIONS'", "'MINIMUM_SHOULD_MATCH'", "'OPERATOR'", "'PHRASE_SLOP'", + "'PREFIX_LENGTH'", "'QUOTE_ANALYZER'", "'QUOTE_FIELD_SUFFIX'", "'REWRITE'", + "'SLOP'", "'TIE_BREAKER'", "'TYPE'", "'ZERO_TERMS_QUERY'", "'SPAN'", + "'MS'", "'S'", "'M'", "'H'", "'W'", "'Q'", "'Y'" + }; + } + private static final String[] _LITERAL_NAMES = makeLiteralNames(); + private static String[] makeSymbolicNames() { + return new String[] { + null, "SEARCH", "FROM", "WHERE", "FIELDS", "RENAME", "STATS", "DEDUP", + "SORT", "EVAL", "HEAD", "TOP", "RARE", "PARSE", "KMEANS", "AD", "AS", + "BY", "SOURCE", "INDEX", "D", "DESC", "SORTBY", "AUTO", "STR", "IP", + "NUM", "KEEPEMPTY", "CONSECUTIVE", "DEDUP_SPLITVALUES", "PARTITIONS", + "ALLNUM", "DELIM", "CENTROIDS", "ITERATIONS", "DISTANCE_TYPE", "NUMBER_OF_TREES", + "SHINGLE_SIZE", "SAMPLE_SIZE", "OUTPUT_AFTER", "TIME_DECAY", "ANOMALY_RATE", + "TIME_FIELD", "TIME_ZONE", "TRAINING_DATA_SIZE", "ANOMALY_SCORE_THRESHOLD", + "CASE", "IN", "NOT", "OR", "AND", "XOR", "TRUE", "FALSE", "REGEXP", "DATETIME", + "INTERVAL", "MICROSECOND", "MILLISECOND", "SECOND", "MINUTE", "HOUR", + "DAY", "WEEK", "MONTH", "QUARTER", "YEAR", "SECOND_MICROSECOND", "MINUTE_MICROSECOND", + "MINUTE_SECOND", "HOUR_MICROSECOND", "HOUR_SECOND", "HOUR_MINUTE", "DAY_MICROSECOND", + "DAY_SECOND", "DAY_MINUTE", "DAY_HOUR", "YEAR_MONTH", "DATAMODEL", "LOOKUP", + "SAVEDSEARCH", "INT", "INTEGER", "DOUBLE", "LONG", "FLOAT", "STRING", + "BOOLEAN", "PIPE", "COMMA", "DOT", "EQUAL", "GREATER", "LESS", "NOT_GREATER", + "NOT_LESS", "NOT_EQUAL", "PLUS", "MINUS", "STAR", "DIVIDE", "MODULE", + "EXCLAMATION_SYMBOL", "COLON", "LT_PRTHS", "RT_PRTHS", "LT_SQR_PRTHS", + "RT_SQR_PRTHS", "SINGLE_QUOTE", "DOUBLE_QUOTE", "BACKTICK", "BIT_NOT_OP", + "BIT_AND_OP", "BIT_XOR_OP", "AVG", "COUNT", "DISTINCT_COUNT", "ESTDC", + "ESTDC_ERROR", "MAX", "MEAN", "MEDIAN", "MIN", "MODE", "RANGE", "STDEV", + "STDEVP", "SUM", "SUMSQ", "VAR_SAMP", "VAR_POP", "STDDEV_SAMP", "STDDEV_POP", + "PERCENTILE", "FIRST", "LAST", "LIST", "VALUES", "EARLIEST", "EARLIEST_TIME", + "LATEST", "LATEST_TIME", "PER_DAY", "PER_HOUR", "PER_MINUTE", "PER_SECOND", + "RATE", "SPARKLINE", "C", "DC", "ABS", "CEIL", "CEILING", "CONV", "CRC32", + "E", "EXP", "FLOOR", "LN", "LOG", "LOG10", "LOG2", "MOD", "PI", "POW", + "POWER", "RAND", "ROUND", "SIGN", "SQRT", "TRUNCATE", "ACOS", "ASIN", + "ATAN", "ATAN2", "COS", "COT", "DEGREES", "RADIANS", "SIN", "TAN", "ADDDATE", + "DATE", "DATE_ADD", "DATE_SUB", "DAYOFMONTH", "DAYOFWEEK", "DAYOFYEAR", + "DAYNAME", "FROM_DAYS", "MONTHNAME", "SUBDATE", "TIME", "TIME_TO_SEC", + "TIMESTAMP", "DATE_FORMAT", "TO_DAYS", "SUBSTR", "SUBSTRING", "LTRIM", + "RTRIM", "TRIM", "TO", "LOWER", "UPPER", "CONCAT", "CONCAT_WS", "LENGTH", + "STRCMP", "RIGHT", "LEFT", "ASCII", "LOCATE", "REPLACE", "CAST", "LIKE", + "ISNULL", "ISNOTNULL", "IFNULL", "NULLIF", "IF", "MATCH", "MATCH_PHRASE", + "SIMPLE_QUERY_STRING", "ALLOW_LEADING_WILDCARD", "ANALYZE_WILDCARD", + "ANALYZER", "AUTO_GENERATE_SYNONYMS_PHRASE_QUERY", "BOOST", "CUTOFF_FREQUENCY", + "DEFAULT_FIELD", "DEFAULT_OPERATOR", "ENABLE_POSITION_INCREMENTS", "FLAGS", + "FUZZY_MAX_EXPANSIONS", "FUZZY_PREFIX_LENGTH", "FUZZY_TRANSPOSITIONS", + "FUZZY_REWRITE", "FUZZINESS", "LENIENT", "LOW_FREQ_OPERATOR", "MAX_DETERMINIZED_STATES", + "MAX_EXPANSIONS", "MINIMUM_SHOULD_MATCH", "OPERATOR", "PHRASE_SLOP", + "PREFIX_LENGTH", "QUOTE_ANALYZER", "QUOTE_FIELD_SUFFIX", "REWRITE", "SLOP", + "TIE_BREAKER", "TYPE", "ZERO_TERMS_QUERY", "SPAN", "MS", "S", "M", "H", + "W", "Q", "Y", "ID", "INTEGER_LITERAL", "DECIMAL_LITERAL", "ID_DATE_SUFFIX", + "DQUOTA_STRING", "SQUOTA_STRING", "BQUOTA_STRING", "ERROR_RECOGNITION" + }; + } + private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + + public OpenSearchPPLLexer(CharStream input) { + super(input); + _interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); + } + + @Override + public String getGrammarFileName() { return "OpenSearchPPLLexer.g4"; } + + @Override + public String[] getRuleNames() { return ruleNames; } + + @Override + public String getSerializedATN() { return _serializedATN; } + + @Override + public String[] getChannelNames() { return channelNames; } + + @Override + public String[] getModeNames() { return modeNames; } + + @Override + public ATN getATN() { return _ATN; } + + private static final int _serializedATNSegments = 2; + private static final String _serializedATNSegment0 = + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\u010f\u0a6f\b\1\4"+ + "\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n"+ + "\4\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22"+ + "\t\22\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31"+ + "\t\31\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t"+ + " \4!\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t"+ + "+\4,\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62\4\63\t\63\4\64"+ + "\t\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\4:\t:\4;\t;\4<\t<\4=\t"+ + "=\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\4E\tE\4F\tF\4G\tG\4H\tH\4"+ + "I\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\4S\tS\4T\t"+ + "T\4U\tU\4V\tV\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]\t]\4^\t^\4_\t_"+ + "\4`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\4g\tg\4h\th\4i\ti\4j\tj\4k"+ + "\tk\4l\tl\4m\tm\4n\tn\4o\to\4p\tp\4q\tq\4r\tr\4s\ts\4t\tt\4u\tu\4v\tv"+ + "\4w\tw\4x\tx\4y\ty\4z\tz\4{\t{\4|\t|\4}\t}\4~\t~\4\177\t\177\4\u0080\t"+ + "\u0080\4\u0081\t\u0081\4\u0082\t\u0082\4\u0083\t\u0083\4\u0084\t\u0084"+ + "\4\u0085\t\u0085\4\u0086\t\u0086\4\u0087\t\u0087\4\u0088\t\u0088\4\u0089"+ + "\t\u0089\4\u008a\t\u008a\4\u008b\t\u008b\4\u008c\t\u008c\4\u008d\t\u008d"+ + "\4\u008e\t\u008e\4\u008f\t\u008f\4\u0090\t\u0090\4\u0091\t\u0091\4\u0092"+ + "\t\u0092\4\u0093\t\u0093\4\u0094\t\u0094\4\u0095\t\u0095\4\u0096\t\u0096"+ + "\4\u0097\t\u0097\4\u0098\t\u0098\4\u0099\t\u0099\4\u009a\t\u009a\4\u009b"+ + "\t\u009b\4\u009c\t\u009c\4\u009d\t\u009d\4\u009e\t\u009e\4\u009f\t\u009f"+ + "\4\u00a0\t\u00a0\4\u00a1\t\u00a1\4\u00a2\t\u00a2\4\u00a3\t\u00a3\4\u00a4"+ + "\t\u00a4\4\u00a5\t\u00a5\4\u00a6\t\u00a6\4\u00a7\t\u00a7\4\u00a8\t\u00a8"+ + "\4\u00a9\t\u00a9\4\u00aa\t\u00aa\4\u00ab\t\u00ab\4\u00ac\t\u00ac\4\u00ad"+ + "\t\u00ad\4\u00ae\t\u00ae\4\u00af\t\u00af\4\u00b0\t\u00b0\4\u00b1\t\u00b1"+ + "\4\u00b2\t\u00b2\4\u00b3\t\u00b3\4\u00b4\t\u00b4\4\u00b5\t\u00b5\4\u00b6"+ + "\t\u00b6\4\u00b7\t\u00b7\4\u00b8\t\u00b8\4\u00b9\t\u00b9\4\u00ba\t\u00ba"+ + "\4\u00bb\t\u00bb\4\u00bc\t\u00bc\4\u00bd\t\u00bd\4\u00be\t\u00be\4\u00bf"+ + "\t\u00bf\4\u00c0\t\u00c0\4\u00c1\t\u00c1\4\u00c2\t\u00c2\4\u00c3\t\u00c3"+ + "\4\u00c4\t\u00c4\4\u00c5\t\u00c5\4\u00c6\t\u00c6\4\u00c7\t\u00c7\4\u00c8"+ + "\t\u00c8\4\u00c9\t\u00c9\4\u00ca\t\u00ca\4\u00cb\t\u00cb\4\u00cc\t\u00cc"+ + "\4\u00cd\t\u00cd\4\u00ce\t\u00ce\4\u00cf\t\u00cf\4\u00d0\t\u00d0\4\u00d1"+ + "\t\u00d1\4\u00d2\t\u00d2\4\u00d3\t\u00d3\4\u00d4\t\u00d4\4\u00d5\t\u00d5"+ + "\4\u00d6\t\u00d6\4\u00d7\t\u00d7\4\u00d8\t\u00d8\4\u00d9\t\u00d9\4\u00da"+ + "\t\u00da\4\u00db\t\u00db\4\u00dc\t\u00dc\4\u00dd\t\u00dd\4\u00de\t\u00de"+ + "\4\u00df\t\u00df\4\u00e0\t\u00e0\4\u00e1\t\u00e1\4\u00e2\t\u00e2\4\u00e3"+ + "\t\u00e3\4\u00e4\t\u00e4\4\u00e5\t\u00e5\4\u00e6\t\u00e6\4\u00e7\t\u00e7"+ + "\4\u00e8\t\u00e8\4\u00e9\t\u00e9\4\u00ea\t\u00ea\4\u00eb\t\u00eb\4\u00ec"+ + "\t\u00ec\4\u00ed\t\u00ed\4\u00ee\t\u00ee\4\u00ef\t\u00ef\4\u00f0\t\u00f0"+ + "\4\u00f1\t\u00f1\4\u00f2\t\u00f2\4\u00f3\t\u00f3\4\u00f4\t\u00f4\4\u00f5"+ + "\t\u00f5\4\u00f6\t\u00f6\4\u00f7\t\u00f7\4\u00f8\t\u00f8\4\u00f9\t\u00f9"+ + "\4\u00fa\t\u00fa\4\u00fb\t\u00fb\4\u00fc\t\u00fc\4\u00fd\t\u00fd\4\u00fe"+ + "\t\u00fe\4\u00ff\t\u00ff\4\u0100\t\u0100\4\u0101\t\u0101\4\u0102\t\u0102"+ + "\4\u0103\t\u0103\4\u0104\t\u0104\4\u0105\t\u0105\4\u0106\t\u0106\4\u0107"+ + "\t\u0107\4\u0108\t\u0108\4\u0109\t\u0109\4\u010a\t\u010a\4\u010b\t\u010b"+ + "\4\u010c\t\u010c\4\u010d\t\u010d\4\u010e\t\u010e\4\u010f\t\u010f\4\u0110"+ + "\t\u0110\4\u0111\t\u0111\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\3\3\3\3\3\3\3\3"+ + "\3\3\4\3\4\3\4\3\4\3\4\3\4\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6"+ + "\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\b\3\t\3\t\3"+ + "\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3"+ + "\f\3\r\3\r\3\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3"+ + "\17\3\17\3\17\3\17\3\20\3\20\3\20\3\21\3\21\3\21\3\22\3\22\3\22\3\23\3"+ + "\23\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3"+ + "\26\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\30\3\30\3"+ + "\30\3\30\3\30\3\31\3\31\3\31\3\31\3\32\3\32\3\32\3\33\3\33\3\33\3\33\3"+ + "\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\34\3\35\3\35\3\35\3\35\3"+ + "\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\36\3\36\3\36\3\36\3\36\3\36\3"+ + "\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\37\3\37\3"+ + "\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3 \3 \3 \3 \3 \3 \3 \3!\3"+ + "!\3!\3!\3!\3!\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3\"\3#\3#\3#\3#\3#\3"+ + "#\3#\3#\3#\3#\3#\3$\3$\3$\3$\3$\3$\3$\3$\3$\3$\3$\3$\3$\3$\3%\3%\3%\3"+ + "%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3%\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3"+ + "&\3&\3&\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3(\3(\3(\3(\3"+ + "(\3(\3(\3(\3(\3(\3(\3(\3(\3)\3)\3)\3)\3)\3)\3)\3)\3)\3)\3)\3*\3*\3*\3"+ + "*\3*\3*\3*\3*\3*\3*\3*\3*\3*\3+\3+\3+\3+\3+\3+\3+\3+\3+\3+\3+\3,\3,\3"+ + ",\3,\3,\3,\3,\3,\3,\3,\3-\3-\3-\3-\3-\3-\3-\3-\3-\3-\3-\3-\3-\3-\3-\3"+ + "-\3-\3-\3-\3.\3.\3.\3.\3.\3.\3.\3.\3.\3.\3.\3.\3.\3.\3.\3.\3.\3.\3.\3"+ + ".\3.\3.\3.\3.\3/\3/\3/\3/\3/\3\60\3\60\3\60\3\61\3\61\3\61\3\61\3\62\3"+ + "\62\3\62\3\63\3\63\3\63\3\63\3\64\3\64\3\64\3\64\3\65\3\65\3\65\3\65\3"+ + "\65\3\66\3\66\3\66\3\66\3\66\3\66\3\67\3\67\3\67\3\67\3\67\3\67\3\67\3"+ + "8\38\38\38\38\38\38\38\38\39\39\39\39\39\39\39\39\39\3:\3:\3:\3:\3:\3"+ + ":\3:\3:\3:\3:\3:\3:\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3;\3<\3<\3<\3<\3"+ + "<\3<\3<\3=\3=\3=\3=\3=\3=\3=\3>\3>\3>\3>\3>\3?\3?\3?\3?\3@\3@\3@\3@\3"+ + "@\3A\3A\3A\3A\3A\3A\3B\3B\3B\3B\3B\3B\3B\3B\3C\3C\3C\3C\3C\3D\3D\3D\3"+ + "D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3D\3E\3E\3E\3E\3E\3E\3E\3"+ + "E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3E\3F\3F\3F\3F\3F\3F\3F\3F\3F\3F\3F\3"+ + "F\3F\3F\3G\3G\3G\3G\3G\3G\3G\3G\3G\3G\3G\3G\3G\3G\3G\3G\3G\3H\3H\3H\3"+ + "H\3H\3H\3H\3H\3H\3H\3H\3H\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3J\3J\3"+ + "J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3K\3K\3K\3K\3K\3K\3K\3K\3K\3"+ + "K\3K\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3M\3M\3M\3M\3M\3M\3M\3M\3M\3N\3"+ + "N\3N\3N\3N\3N\3N\3N\3N\3N\3N\3O\3O\3O\3O\3O\3O\3O\3O\3O\3O\3P\3P\3P\3"+ + "P\3P\3P\3P\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3R\3R\3R\3R\3S\3S\3S\3"+ + "S\3S\3S\3S\3S\3T\3T\3T\3T\3T\3T\3T\3U\3U\3U\3U\3U\3V\3V\3V\3V\3V\3V\3"+ + "W\3W\3W\3W\3W\3W\3W\3X\3X\3X\3X\3X\3X\3X\3X\3Y\3Y\3Z\3Z\3[\3[\3\\\3\\"+ + "\3]\3]\3^\3^\3_\3_\3_\3`\3`\3`\3a\3a\3a\3b\3b\3c\3c\3d\3d\3e\3e\3f\3f"+ + "\3g\3g\3h\3h\3i\3i\3j\3j\3k\3k\3l\3l\3m\3m\3n\3n\3o\3o\3p\3p\3q\3q\3r"+ + "\3r\3s\3s\3s\3s\3t\3t\3t\3t\3t\3t\3u\3u\3u\3u\3u\3u\3u\3u\3u\3u\3u\3u"+ + "\3u\3u\3u\3v\3v\3v\3v\3v\3v\3w\3w\3w\3w\3w\3w\3w\3w\3w\3w\3w\3w\3x\3x"+ + "\3x\3x\3y\3y\3y\3y\3y\3z\3z\3z\3z\3z\3z\3z\3{\3{\3{\3{\3|\3|\3|\3|\3|"+ + "\3}\3}\3}\3}\3}\3}\3~\3~\3~\3~\3~\3~\3\177\3\177\3\177\3\177\3\177\3\177"+ + "\3\177\3\u0080\3\u0080\3\u0080\3\u0080\3\u0081\3\u0081\3\u0081\3\u0081"+ + "\3\u0081\3\u0081\3\u0082\3\u0082\3\u0082\3\u0082\3\u0082\3\u0082\3\u0082"+ + "\3\u0082\3\u0082\3\u0083\3\u0083\3\u0083\3\u0083\3\u0083\3\u0083\3\u0083"+ + "\3\u0083\3\u0084\3\u0084\3\u0084\3\u0084\3\u0084\3\u0084\3\u0084\3\u0084"+ + "\3\u0084\3\u0084\3\u0084\3\u0084\3\u0085\3\u0085\3\u0085\3\u0085\3\u0085"+ + "\3\u0085\3\u0085\3\u0085\3\u0085\3\u0085\3\u0085\3\u0086\3\u0086\3\u0086"+ + "\3\u0086\3\u0086\3\u0086\3\u0086\3\u0086\3\u0086\3\u0086\3\u0086\3\u0087"+ + "\3\u0087\3\u0087\3\u0087\3\u0087\3\u0087\3\u0088\3\u0088\3\u0088\3\u0088"+ + "\3\u0088\3\u0089\3\u0089\3\u0089\3\u0089\3\u0089\3\u008a\3\u008a\3\u008a"+ + "\3\u008a\3\u008a\3\u008a\3\u008a\3\u008b\3\u008b\3\u008b\3\u008b\3\u008b"+ + "\3\u008b\3\u008b\3\u008b\3\u008b\3\u008c\3\u008c\3\u008c\3\u008c\3\u008c"+ + "\3\u008c\3\u008c\3\u008c\3\u008c\3\u008c\3\u008c\3\u008c\3\u008c\3\u008c"+ + "\3\u008d\3\u008d\3\u008d\3\u008d\3\u008d\3\u008d\3\u008d\3\u008e\3\u008e"+ + "\3\u008e\3\u008e\3\u008e\3\u008e\3\u008e\3\u008e\3\u008e\3\u008e\3\u008e"+ + "\3\u008e\3\u008f\3\u008f\3\u008f\3\u008f\3\u008f\3\u008f\3\u008f\3\u008f"+ + "\3\u0090\3\u0090\3\u0090\3\u0090\3\u0090\3\u0090\3\u0090\3\u0090\3\u0090"+ + "\3\u0091\3\u0091\3\u0091\3\u0091\3\u0091\3\u0091\3\u0091\3\u0091\3\u0091"+ + "\3\u0091\3\u0091\3\u0092\3\u0092\3\u0092\3\u0092\3\u0092\3\u0092\3\u0092"+ + "\3\u0092\3\u0092\3\u0092\3\u0092\3\u0093\3\u0093\3\u0093\3\u0093\3\u0093"+ + "\3\u0094\3\u0094\3\u0094\3\u0094\3\u0094\3\u0094\3\u0094\3\u0094\3\u0094"+ + "\3\u0094\3\u0095\3\u0095\3\u0096\3\u0096\3\u0096\3\u0097\3\u0097\3\u0097"+ + "\3\u0097\3\u0098\3\u0098\3\u0098\3\u0098\3\u0098\3\u0099\3\u0099\3\u0099"+ + "\3\u0099\3\u0099\3\u0099\3\u0099\3\u0099\3\u009a\3\u009a\3\u009a\3\u009a"+ + "\3\u009a\3\u009b\3\u009b\3\u009b\3\u009b\3\u009b\3\u009b\3\u009c\3\u009c"+ + "\3\u009d\3\u009d\3\u009d\3\u009d\3\u009e\3\u009e\3\u009e\3\u009e\3\u009e"+ + "\3\u009e\3\u009f\3\u009f\3\u009f\3\u00a0\3\u00a0\3\u00a0\3\u00a0\3\u00a1"+ + "\3\u00a1\3\u00a1\3\u00a1\3\u00a1\3\u00a1\3\u00a2\3\u00a2\3\u00a2\3\u00a2"+ + "\3\u00a2\3\u00a3\3\u00a3\3\u00a3\3\u00a3\3\u00a4\3\u00a4\3\u00a4\3\u00a5"+ + "\3\u00a5\3\u00a5\3\u00a5\3\u00a6\3\u00a6\3\u00a6\3\u00a6\3\u00a6\3\u00a6"+ + "\3\u00a7\3\u00a7\3\u00a7\3\u00a7\3\u00a7\3\u00a8\3\u00a8\3\u00a8\3\u00a8"+ + "\3\u00a8\3\u00a8\3\u00a9\3\u00a9\3\u00a9\3\u00a9\3\u00a9\3\u00aa\3\u00aa"+ + "\3\u00aa\3\u00aa\3\u00aa\3\u00ab\3\u00ab\3\u00ab\3\u00ab\3\u00ab\3\u00ab"+ + "\3\u00ab\3\u00ab\3\u00ab\3\u00ac\3\u00ac\3\u00ac\3\u00ac\3\u00ac\3\u00ad"+ + "\3\u00ad\3\u00ad\3\u00ad\3\u00ad\3\u00ae\3\u00ae\3\u00ae\3\u00ae\3\u00ae"+ + "\3\u00af\3\u00af\3\u00af\3\u00af\3\u00af\3\u00af\3\u00b0\3\u00b0\3\u00b0"+ + "\3\u00b0\3\u00b1\3\u00b1\3\u00b1\3\u00b1\3\u00b2\3\u00b2\3\u00b2\3\u00b2"+ + "\3\u00b2\3\u00b2\3\u00b2\3\u00b2\3\u00b3\3\u00b3\3\u00b3\3\u00b3\3\u00b3"+ + "\3\u00b3\3\u00b3\3\u00b3\3\u00b4\3\u00b4\3\u00b4\3\u00b4\3\u00b5\3\u00b5"+ + "\3\u00b5\3\u00b5\3\u00b6\3\u00b6\3\u00b6\3\u00b6\3\u00b6\3\u00b6\3\u00b6"+ + "\3\u00b6\3\u00b7\3\u00b7\3\u00b7\3\u00b7\3\u00b7\3\u00b8\3\u00b8\3\u00b8"+ + "\3\u00b8\3\u00b8\3\u00b8\3\u00b8\3\u00b8\3\u00b8\3\u00b9\3\u00b9\3\u00b9"+ + "\3\u00b9\3\u00b9\3\u00b9\3\u00b9\3\u00b9\3\u00b9\3\u00ba\3\u00ba\3\u00ba"+ + "\3\u00ba\3\u00ba\3\u00ba\3\u00ba\3\u00ba\3\u00ba\3\u00ba\3\u00ba\3\u00bb"+ + "\3\u00bb\3\u00bb\3\u00bb\3\u00bb\3\u00bb\3\u00bb\3\u00bb\3\u00bb\3\u00bb"+ + "\3\u00bc\3\u00bc\3\u00bc\3\u00bc\3\u00bc\3\u00bc\3\u00bc\3\u00bc\3\u00bc"+ + "\3\u00bc\3\u00bd\3\u00bd\3\u00bd\3\u00bd\3\u00bd\3\u00bd\3\u00bd\3\u00bd"+ + "\3\u00be\3\u00be\3\u00be\3\u00be\3\u00be\3\u00be\3\u00be\3\u00be\3\u00be"+ + "\3\u00be\3\u00bf\3\u00bf\3\u00bf\3\u00bf\3\u00bf\3\u00bf\3\u00bf\3\u00bf"+ + "\3\u00bf\3\u00bf\3\u00c0\3\u00c0\3\u00c0\3\u00c0\3\u00c0\3\u00c0\3\u00c0"+ + "\3\u00c0\3\u00c1\3\u00c1\3\u00c1\3\u00c1\3\u00c1\3\u00c2\3\u00c2\3\u00c2"+ + "\3\u00c2\3\u00c2\3\u00c2\3\u00c2\3\u00c2\3\u00c2\3\u00c2\3\u00c2\3\u00c2"+ + "\3\u00c3\3\u00c3\3\u00c3\3\u00c3\3\u00c3\3\u00c3\3\u00c3\3\u00c3\3\u00c3"+ + "\3\u00c3\3\u00c4\3\u00c4\3\u00c4\3\u00c4\3\u00c4\3\u00c4\3\u00c4\3\u00c4"+ + "\3\u00c4\3\u00c4\3\u00c4\3\u00c4\3\u00c5\3\u00c5\3\u00c5\3\u00c5\3\u00c5"+ + "\3\u00c5\3\u00c5\3\u00c5\3\u00c6\3\u00c6\3\u00c6\3\u00c6\3\u00c6\3\u00c6"+ + "\3\u00c6\3\u00c7\3\u00c7\3\u00c7\3\u00c7\3\u00c7\3\u00c7\3\u00c7\3\u00c7"+ + "\3\u00c7\3\u00c7\3\u00c8\3\u00c8\3\u00c8\3\u00c8\3\u00c8\3\u00c8\3\u00c9"+ + "\3\u00c9\3\u00c9\3\u00c9\3\u00c9\3\u00c9\3\u00ca\3\u00ca\3\u00ca\3\u00ca"+ + "\3\u00ca\3\u00cb\3\u00cb\3\u00cb\3\u00cc\3\u00cc\3\u00cc\3\u00cc\3\u00cc"+ + "\3\u00cc\3\u00cd\3\u00cd\3\u00cd\3\u00cd\3\u00cd\3\u00cd\3\u00ce\3\u00ce"+ + "\3\u00ce\3\u00ce\3\u00ce\3\u00ce\3\u00ce\3\u00cf\3\u00cf\3\u00cf\3\u00cf"+ + "\3\u00cf\3\u00cf\3\u00cf\3\u00cf\3\u00cf\3\u00cf\3\u00d0\3\u00d0\3\u00d0"+ + "\3\u00d0\3\u00d0\3\u00d0\3\u00d0\3\u00d1\3\u00d1\3\u00d1\3\u00d1\3\u00d1"+ + "\3\u00d1\3\u00d1\3\u00d2\3\u00d2\3\u00d2\3\u00d2\3\u00d2\3\u00d2\3\u00d3"+ + "\3\u00d3\3\u00d3\3\u00d3\3\u00d3\3\u00d4\3\u00d4\3\u00d4\3\u00d4\3\u00d4"+ + "\3\u00d4\3\u00d5\3\u00d5\3\u00d5\3\u00d5\3\u00d5\3\u00d5\3\u00d5\3\u00d6"+ + "\3\u00d6\3\u00d6\3\u00d6\3\u00d6\3\u00d6\3\u00d6\3\u00d6\3\u00d7\3\u00d7"+ + "\3\u00d7\3\u00d7\3\u00d7\3\u00d8\3\u00d8\3\u00d8\3\u00d8\3\u00d8\3\u00d9"+ + "\3\u00d9\3\u00d9\3\u00d9\3\u00d9\3\u00d9\3\u00d9\3\u00da\3\u00da\3\u00da"+ + "\3\u00da\3\u00da\3\u00da\3\u00da\3\u00da\3\u00da\3\u00da\3\u00db\3\u00db"+ + "\3\u00db\3\u00db\3\u00db\3\u00db\3\u00db\3\u00dc\3\u00dc\3\u00dc\3\u00dc"+ + "\3\u00dc\3\u00dc\3\u00dc\3\u00dd\3\u00dd\3\u00dd\3\u00de\3\u00de\3\u00de"+ + "\3\u00de\3\u00de\3\u00de\3\u00df\3\u00df\3\u00df\3\u00df\3\u00df\3\u00df"+ + "\3\u00df\3\u00df\3\u00df\3\u00df\3\u00df\3\u00df\3\u00df\3\u00e0\3\u00e0"+ + "\3\u00e0\3\u00e0\3\u00e0\3\u00e0\3\u00e0\3\u00e0\3\u00e0\3\u00e0\3\u00e0"+ + "\3\u00e0\3\u00e0\3\u00e0\3\u00e0\3\u00e0\3\u00e0\3\u00e0\3\u00e0\3\u00e0"+ + "\3\u00e1\3\u00e1\3\u00e1\3\u00e1\3\u00e1\3\u00e1\3\u00e1\3\u00e1\3\u00e1"+ + "\3\u00e1\3\u00e1\3\u00e1\3\u00e1\3\u00e1\3\u00e1\3\u00e1\3\u00e1\3\u00e1"+ + "\3\u00e1\3\u00e1\3\u00e1\3\u00e1\3\u00e1\3\u00e2\3\u00e2\3\u00e2\3\u00e2"+ + "\3\u00e2\3\u00e2\3\u00e2\3\u00e2\3\u00e2\3\u00e2\3\u00e2\3\u00e2\3\u00e2"+ + "\3\u00e2\3\u00e2\3\u00e2\3\u00e2\3\u00e3\3\u00e3\3\u00e3\3\u00e3\3\u00e3"+ + "\3\u00e3\3\u00e3\3\u00e3\3\u00e3\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e4"+ + "\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e4"+ + "\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e4"+ + "\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e4"+ + "\3\u00e4\3\u00e4\3\u00e4\3\u00e4\3\u00e5\3\u00e5\3\u00e5\3\u00e5\3\u00e5"+ + "\3\u00e5\3\u00e6\3\u00e6\3\u00e6\3\u00e6\3\u00e6\3\u00e6\3\u00e6\3\u00e6"+ + "\3\u00e6\3\u00e6\3\u00e6\3\u00e6\3\u00e6\3\u00e6\3\u00e6\3\u00e6\3\u00e6"+ + "\3\u00e7\3\u00e7\3\u00e7\3\u00e7\3\u00e7\3\u00e7\3\u00e7\3\u00e7\3\u00e7"+ + "\3\u00e7\3\u00e7\3\u00e7\3\u00e7\3\u00e7\3\u00e8\3\u00e8\3\u00e8\3\u00e8"+ + "\3\u00e8\3\u00e8\3\u00e8\3\u00e8\3\u00e8\3\u00e8\3\u00e8\3\u00e8\3\u00e8"+ + "\3\u00e8\3\u00e8\3\u00e8\3\u00e8\3\u00e9\3\u00e9\3\u00e9\3\u00e9\3\u00e9"+ + "\3\u00e9\3\u00e9\3\u00e9\3\u00e9\3\u00e9\3\u00e9\3\u00e9\3\u00e9\3\u00e9"+ + "\3\u00e9\3\u00e9\3\u00e9\3\u00e9\3\u00e9\3\u00e9\3\u00e9\3\u00e9\3\u00e9"+ + "\3\u00e9\3\u00e9\3\u00e9\3\u00e9\3\u00ea\3\u00ea\3\u00ea\3\u00ea\3\u00ea"+ + "\3\u00ea\3\u00eb\3\u00eb\3\u00eb\3\u00eb\3\u00eb\3\u00eb\3\u00eb\3\u00eb"+ + "\3\u00eb\3\u00eb\3\u00eb\3\u00eb\3\u00eb\3\u00eb\3\u00eb\3\u00eb\3\u00eb"+ + "\3\u00eb\3\u00eb\3\u00eb\3\u00eb\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ec"+ + "\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ec"+ + "\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ec\3\u00ed\3\u00ed\3\u00ed"+ + "\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ed"+ + "\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ed\3\u00ed"+ + "\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ee"+ + "\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ee\3\u00ef\3\u00ef\3\u00ef\3\u00ef"+ + "\3\u00ef\3\u00ef\3\u00ef\3\u00ef\3\u00ef\3\u00ef\3\u00f0\3\u00f0\3\u00f0"+ + "\3\u00f0\3\u00f0\3\u00f0\3\u00f0\3\u00f0\3\u00f1\3\u00f1\3\u00f1\3\u00f1"+ + "\3\u00f1\3\u00f1\3\u00f1\3\u00f1\3\u00f1\3\u00f1\3\u00f1\3\u00f1\3\u00f1"+ + "\3\u00f1\3\u00f1\3\u00f1\3\u00f1\3\u00f1\3\u00f2\3\u00f2\3\u00f2\3\u00f2"+ + "\3\u00f2\3\u00f2\3\u00f2\3\u00f2\3\u00f2\3\u00f2\3\u00f2\3\u00f2\3\u00f2"+ + "\3\u00f2\3\u00f2\3\u00f2\3\u00f2\3\u00f2\3\u00f2\3\u00f2\3\u00f2\3\u00f2"+ + "\3\u00f2\3\u00f2\3\u00f3\3\u00f3\3\u00f3\3\u00f3\3\u00f3\3\u00f3\3\u00f3"+ + "\3\u00f3\3\u00f3\3\u00f3\3\u00f3\3\u00f3\3\u00f3\3\u00f3\3\u00f3\3\u00f4"+ + "\3\u00f4\3\u00f4\3\u00f4\3\u00f4\3\u00f4\3\u00f4\3\u00f4\3\u00f4\3\u00f4"+ + "\3\u00f4\3\u00f4\3\u00f4\3\u00f4\3\u00f4\3\u00f4\3\u00f4\3\u00f4\3\u00f4"+ + "\3\u00f4\3\u00f4\3\u00f5\3\u00f5\3\u00f5\3\u00f5\3\u00f5\3\u00f5\3\u00f5"+ + "\3\u00f5\3\u00f5\3\u00f6\3\u00f6\3\u00f6\3\u00f6\3\u00f6\3\u00f6\3\u00f6"+ + "\3\u00f6\3\u00f6\3\u00f6\3\u00f6\3\u00f6\3\u00f7\3\u00f7\3\u00f7\3\u00f7"+ + "\3\u00f7\3\u00f7\3\u00f7\3\u00f7\3\u00f7\3\u00f7\3\u00f7\3\u00f7\3\u00f7"+ + "\3\u00f7\3\u00f8\3\u00f8\3\u00f8\3\u00f8\3\u00f8\3\u00f8\3\u00f8\3\u00f8"+ + "\3\u00f8\3\u00f8\3\u00f8\3\u00f8\3\u00f8\3\u00f8\3\u00f8\3\u00f9\3\u00f9"+ + "\3\u00f9\3\u00f9\3\u00f9\3\u00f9\3\u00f9\3\u00f9\3\u00f9\3\u00f9\3\u00f9"+ + "\3\u00f9\3\u00f9\3\u00f9\3\u00f9\3\u00f9\3\u00f9\3\u00f9\3\u00f9\3\u00fa"+ + "\3\u00fa\3\u00fa\3\u00fa\3\u00fa\3\u00fa\3\u00fa\3\u00fa\3\u00fb\3\u00fb"+ + "\3\u00fb\3\u00fb\3\u00fb\3\u00fc\3\u00fc\3\u00fc\3\u00fc\3\u00fc\3\u00fc"+ + "\3\u00fc\3\u00fc\3\u00fc\3\u00fc\3\u00fc\3\u00fc\3\u00fd\3\u00fd\3\u00fd"+ + "\3\u00fd\3\u00fd\3\u00fe\3\u00fe\3\u00fe\3\u00fe\3\u00fe\3\u00fe\3\u00fe"+ + "\3\u00fe\3\u00fe\3\u00fe\3\u00fe\3\u00fe\3\u00fe\3\u00fe\3\u00fe\3\u00fe"+ + "\3\u00fe\3\u00ff\3\u00ff\3\u00ff\3\u00ff\3\u00ff\3\u0100\3\u0100\3\u0100"+ + "\3\u0101\3\u0101\3\u0102\3\u0102\3\u0103\3\u0103\3\u0104\3\u0104\3\u0105"+ + "\3\u0105\3\u0106\3\u0106\3\u0107\3\u0107\3\u0108\6\u0108\u0a19\n\u0108"+ + "\r\u0108\16\u0108\u0a1a\3\u0109\6\u0109\u0a1e\n\u0109\r\u0109\16\u0109"+ + "\u0a1f\5\u0109\u0a22\n\u0109\3\u0109\3\u0109\6\u0109\u0a26\n\u0109\r\u0109"+ + "\16\u0109\u0a27\3\u010a\3\u010a\6\u010a\u0a2c\n\u010a\r\u010a\16\u010a"+ + "\u0a2d\7\u010a\u0a30\n\u010a\f\u010a\16\u010a\u0a33\13\u010a\3\u010b\6"+ + "\u010b\u0a36\n\u010b\r\u010b\16\u010b\u0a37\3\u010b\7\u010b\u0a3b\n\u010b"+ + "\f\u010b\16\u010b\u0a3e\13\u010b\3\u010c\3\u010c\3\u010c\3\u010d\3\u010d"+ + "\3\u010d\3\u010d\3\u010d\3\u010d\7\u010d\u0a49\n\u010d\f\u010d\16\u010d"+ + "\u0a4c\13\u010d\3\u010d\3\u010d\3\u010e\3\u010e\3\u010e\3\u010e\3\u010e"+ + "\3\u010e\7\u010e\u0a56\n\u010e\f\u010e\16\u010e\u0a59\13\u010e\3\u010e"+ + "\3\u010e\3\u010f\3\u010f\3\u010f\3\u010f\3\u010f\3\u010f\7\u010f\u0a63"+ + "\n\u010f\f\u010f\16\u010f\u0a66\13\u010f\3\u010f\3\u010f\3\u0110\3\u0110"+ + "\3\u0111\3\u0111\3\u0111\3\u0111\3\u0a37\2\u0112\3\3\5\4\7\5\t\6\13\7"+ + "\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25"+ + ")\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O"+ + ")Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67m8o9q:s;u{?}@\177A\u0081"+ + "B\u0083C\u0085D\u0087E\u0089F\u008bG\u008dH\u008fI\u0091J\u0093K\u0095"+ + "L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7U\u00a9"+ + "V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5\\\u00b7]\u00b9^\u00bb_\u00bd"+ + "`\u00bfa\u00c1b\u00c3c\u00c5d\u00c7e\u00c9f\u00cbg\u00cdh\u00cfi\u00d1"+ + "j\u00d3k\u00d5l\u00d7m\u00d9n\u00dbo\u00ddp\u00dfq\u00e1r\u00e3s\u00e5"+ + "t\u00e7u\u00e9v\u00ebw\u00edx\u00efy\u00f1z\u00f3{\u00f5|\u00f7}\u00f9"+ + "~\u00fb\177\u00fd\u0080\u00ff\u0081\u0101\u0082\u0103\u0083\u0105\u0084"+ + "\u0107\u0085\u0109\u0086\u010b\u0087\u010d\u0088\u010f\u0089\u0111\u008a"+ + "\u0113\u008b\u0115\u008c\u0117\u008d\u0119\u008e\u011b\u008f\u011d\u0090"+ + "\u011f\u0091\u0121\u0092\u0123\u0093\u0125\u0094\u0127\u0095\u0129\u0096"+ + "\u012b\u0097\u012d\u0098\u012f\u0099\u0131\u009a\u0133\u009b\u0135\u009c"+ + "\u0137\u009d\u0139\u009e\u013b\u009f\u013d\u00a0\u013f\u00a1\u0141\u00a2"+ + "\u0143\u00a3\u0145\u00a4\u0147\u00a5\u0149\u00a6\u014b\u00a7\u014d\u00a8"+ + "\u014f\u00a9\u0151\u00aa\u0153\u00ab\u0155\u00ac\u0157\u00ad\u0159\u00ae"+ + "\u015b\u00af\u015d\u00b0\u015f\u00b1\u0161\u00b2\u0163\u00b3\u0165\u00b4"+ + "\u0167\u00b5\u0169\u00b6\u016b\u00b7\u016d\u00b8\u016f\u00b9\u0171\u00ba"+ + "\u0173\u00bb\u0175\u00bc\u0177\u00bd\u0179\u00be\u017b\u00bf\u017d\u00c0"+ + "\u017f\u00c1\u0181\u00c2\u0183\u00c3\u0185\u00c4\u0187\u00c5\u0189\u00c6"+ + "\u018b\u00c7\u018d\u00c8\u018f\u00c9\u0191\u00ca\u0193\u00cb\u0195\u00cc"+ + "\u0197\u00cd\u0199\u00ce\u019b\u00cf\u019d\u00d0\u019f\u00d1\u01a1\u00d2"+ + "\u01a3\u00d3\u01a5\u00d4\u01a7\u00d5\u01a9\u00d6\u01ab\u00d7\u01ad\u00d8"+ + "\u01af\u00d9\u01b1\u00da\u01b3\u00db\u01b5\u00dc\u01b7\u00dd\u01b9\u00de"+ + "\u01bb\u00df\u01bd\u00e0\u01bf\u00e1\u01c1\u00e2\u01c3\u00e3\u01c5\u00e4"+ + "\u01c7\u00e5\u01c9\u00e6\u01cb\u00e7\u01cd\u00e8\u01cf\u00e9\u01d1\u00ea"+ + "\u01d3\u00eb\u01d5\u00ec\u01d7\u00ed\u01d9\u00ee\u01db\u00ef\u01dd\u00f0"+ + "\u01df\u00f1\u01e1\u00f2\u01e3\u00f3\u01e5\u00f4\u01e7\u00f5\u01e9\u00f6"+ + "\u01eb\u00f7\u01ed\u00f8\u01ef\u00f9\u01f1\u00fa\u01f3\u00fb\u01f5\u00fc"+ + "\u01f7\u00fd\u01f9\u00fe\u01fb\u00ff\u01fd\u0100\u01ff\u0101\u0201\u0102"+ + "\u0203\u0103\u0205\u0104\u0207\u0105\u0209\u0106\u020b\u0107\u020d\u0108"+ + "\u020f\u0109\u0211\u010a\u0213\2\u0215\2\u0217\u010b\u0219\u010c\u021b"+ + "\u010d\u021d\u010e\u021f\2\u0221\u010f\3\2\n\3\2/\60\4\2,,\62;\4\2,,B"+ + "\\\7\2,,//\62;C\\aa\4\2$$^^\4\2))^^\4\2^^bb\3\2\62;\2\u0a7c\2\3\3\2\2"+ + "\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3"+ + "\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2"+ + "\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2"+ + "\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2"+ + "\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3"+ + "\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2"+ + "\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2"+ + "W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3"+ + "\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2"+ + "\2\2q\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2"+ + "}\3\2\2\2\2\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3\2\2"+ + "\2\2\u0087\3\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2\2\2\u008f"+ + "\3\2\2\2\2\u0091\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097\3\2\2"+ + "\2\2\u0099\3\2\2\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2\2\2\u00a1"+ + "\3\2\2\2\2\u00a3\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9\3\2\2"+ + "\2\2\u00ab\3\2\2\2\2\u00ad\3\2\2\2\2\u00af\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3"+ + "\3\2\2\2\2\u00b5\3\2\2\2\2\u00b7\3\2\2\2\2\u00b9\3\2\2\2\2\u00bb\3\2\2"+ + "\2\2\u00bd\3\2\2\2\2\u00bf\3\2\2\2\2\u00c1\3\2\2\2\2\u00c3\3\2\2\2\2\u00c5"+ + "\3\2\2\2\2\u00c7\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb\3\2\2\2\2\u00cd\3\2\2"+ + "\2\2\u00cf\3\2\2\2\2\u00d1\3\2\2\2\2\u00d3\3\2\2\2\2\u00d5\3\2\2\2\2\u00d7"+ + "\3\2\2\2\2\u00d9\3\2\2\2\2\u00db\3\2\2\2\2\u00dd\3\2\2\2\2\u00df\3\2\2"+ + "\2\2\u00e1\3\2\2\2\2\u00e3\3\2\2\2\2\u00e5\3\2\2\2\2\u00e7\3\2\2\2\2\u00e9"+ + "\3\2\2\2\2\u00eb\3\2\2\2\2\u00ed\3\2\2\2\2\u00ef\3\2\2\2\2\u00f1\3\2\2"+ + "\2\2\u00f3\3\2\2\2\2\u00f5\3\2\2\2\2\u00f7\3\2\2\2\2\u00f9\3\2\2\2\2\u00fb"+ + "\3\2\2\2\2\u00fd\3\2\2\2\2\u00ff\3\2\2\2\2\u0101\3\2\2\2\2\u0103\3\2\2"+ + "\2\2\u0105\3\2\2\2\2\u0107\3\2\2\2\2\u0109\3\2\2\2\2\u010b\3\2\2\2\2\u010d"+ + "\3\2\2\2\2\u010f\3\2\2\2\2\u0111\3\2\2\2\2\u0113\3\2\2\2\2\u0115\3\2\2"+ + "\2\2\u0117\3\2\2\2\2\u0119\3\2\2\2\2\u011b\3\2\2\2\2\u011d\3\2\2\2\2\u011f"+ + "\3\2\2\2\2\u0121\3\2\2\2\2\u0123\3\2\2\2\2\u0125\3\2\2\2\2\u0127\3\2\2"+ + "\2\2\u0129\3\2\2\2\2\u012b\3\2\2\2\2\u012d\3\2\2\2\2\u012f\3\2\2\2\2\u0131"+ + "\3\2\2\2\2\u0133\3\2\2\2\2\u0135\3\2\2\2\2\u0137\3\2\2\2\2\u0139\3\2\2"+ + "\2\2\u013b\3\2\2\2\2\u013d\3\2\2\2\2\u013f\3\2\2\2\2\u0141\3\2\2\2\2\u0143"+ + "\3\2\2\2\2\u0145\3\2\2\2\2\u0147\3\2\2\2\2\u0149\3\2\2\2\2\u014b\3\2\2"+ + "\2\2\u014d\3\2\2\2\2\u014f\3\2\2\2\2\u0151\3\2\2\2\2\u0153\3\2\2\2\2\u0155"+ + "\3\2\2\2\2\u0157\3\2\2\2\2\u0159\3\2\2\2\2\u015b\3\2\2\2\2\u015d\3\2\2"+ + "\2\2\u015f\3\2\2\2\2\u0161\3\2\2\2\2\u0163\3\2\2\2\2\u0165\3\2\2\2\2\u0167"+ + "\3\2\2\2\2\u0169\3\2\2\2\2\u016b\3\2\2\2\2\u016d\3\2\2\2\2\u016f\3\2\2"+ + "\2\2\u0171\3\2\2\2\2\u0173\3\2\2\2\2\u0175\3\2\2\2\2\u0177\3\2\2\2\2\u0179"+ + "\3\2\2\2\2\u017b\3\2\2\2\2\u017d\3\2\2\2\2\u017f\3\2\2\2\2\u0181\3\2\2"+ + "\2\2\u0183\3\2\2\2\2\u0185\3\2\2\2\2\u0187\3\2\2\2\2\u0189\3\2\2\2\2\u018b"+ + "\3\2\2\2\2\u018d\3\2\2\2\2\u018f\3\2\2\2\2\u0191\3\2\2\2\2\u0193\3\2\2"+ + "\2\2\u0195\3\2\2\2\2\u0197\3\2\2\2\2\u0199\3\2\2\2\2\u019b\3\2\2\2\2\u019d"+ + "\3\2\2\2\2\u019f\3\2\2\2\2\u01a1\3\2\2\2\2\u01a3\3\2\2\2\2\u01a5\3\2\2"+ + "\2\2\u01a7\3\2\2\2\2\u01a9\3\2\2\2\2\u01ab\3\2\2\2\2\u01ad\3\2\2\2\2\u01af"+ + "\3\2\2\2\2\u01b1\3\2\2\2\2\u01b3\3\2\2\2\2\u01b5\3\2\2\2\2\u01b7\3\2\2"+ + "\2\2\u01b9\3\2\2\2\2\u01bb\3\2\2\2\2\u01bd\3\2\2\2\2\u01bf\3\2\2\2\2\u01c1"+ + "\3\2\2\2\2\u01c3\3\2\2\2\2\u01c5\3\2\2\2\2\u01c7\3\2\2\2\2\u01c9\3\2\2"+ + "\2\2\u01cb\3\2\2\2\2\u01cd\3\2\2\2\2\u01cf\3\2\2\2\2\u01d1\3\2\2\2\2\u01d3"+ + "\3\2\2\2\2\u01d5\3\2\2\2\2\u01d7\3\2\2\2\2\u01d9\3\2\2\2\2\u01db\3\2\2"+ + "\2\2\u01dd\3\2\2\2\2\u01df\3\2\2\2\2\u01e1\3\2\2\2\2\u01e3\3\2\2\2\2\u01e5"+ + "\3\2\2\2\2\u01e7\3\2\2\2\2\u01e9\3\2\2\2\2\u01eb\3\2\2\2\2\u01ed\3\2\2"+ + "\2\2\u01ef\3\2\2\2\2\u01f1\3\2\2\2\2\u01f3\3\2\2\2\2\u01f5\3\2\2\2\2\u01f7"+ + "\3\2\2\2\2\u01f9\3\2\2\2\2\u01fb\3\2\2\2\2\u01fd\3\2\2\2\2\u01ff\3\2\2"+ + "\2\2\u0201\3\2\2\2\2\u0203\3\2\2\2\2\u0205\3\2\2\2\2\u0207\3\2\2\2\2\u0209"+ + "\3\2\2\2\2\u020b\3\2\2\2\2\u020d\3\2\2\2\2\u020f\3\2\2\2\2\u0211\3\2\2"+ + "\2\2\u0217\3\2\2\2\2\u0219\3\2\2\2\2\u021b\3\2\2\2\2\u021d\3\2\2\2\2\u0221"+ + "\3\2\2\2\3\u0223\3\2\2\2\5\u022a\3\2\2\2\7\u022f\3\2\2\2\t\u0235\3\2\2"+ + "\2\13\u023c\3\2\2\2\r\u0243\3\2\2\2\17\u0249\3\2\2\2\21\u024f\3\2\2\2"+ + "\23\u0254\3\2\2\2\25\u0259\3\2\2\2\27\u025e\3\2\2\2\31\u0262\3\2\2\2\33"+ + "\u0267\3\2\2\2\35\u026d\3\2\2\2\37\u0274\3\2\2\2!\u0277\3\2\2\2#\u027a"+ + "\3\2\2\2%\u027d\3\2\2\2\'\u0284\3\2\2\2)\u028a\3\2\2\2+\u028c\3\2\2\2"+ + "-\u0291\3\2\2\2/\u0298\3\2\2\2\61\u029d\3\2\2\2\63\u02a1\3\2\2\2\65\u02a4"+ + "\3\2\2\2\67\u02a8\3\2\2\29\u02b2\3\2\2\2;\u02be\3\2\2\2=\u02d0\3\2\2\2"+ + "?\u02db\3\2\2\2A\u02e2\3\2\2\2C\u02e8\3\2\2\2E\u02f2\3\2\2\2G\u02fd\3"+ + "\2\2\2I\u030b\3\2\2\2K\u031b\3\2\2\2M\u0328\3\2\2\2O\u0334\3\2\2\2Q\u0341"+ + "\3\2\2\2S\u034c\3\2\2\2U\u0359\3\2\2\2W\u0364\3\2\2\2Y\u036e\3\2\2\2["+ + "\u0381\3\2\2\2]\u0399\3\2\2\2_\u039e\3\2\2\2a\u03a1\3\2\2\2c\u03a5\3\2"+ + "\2\2e\u03a8\3\2\2\2g\u03ac\3\2\2\2i\u03b0\3\2\2\2k\u03b5\3\2\2\2m\u03bb"+ + "\3\2\2\2o\u03c2\3\2\2\2q\u03cb\3\2\2\2s\u03d4\3\2\2\2u\u03e0\3\2\2\2w"+ + "\u03ec\3\2\2\2y\u03f3\3\2\2\2{\u03fa\3\2\2\2}\u03ff\3\2\2\2\177\u0403"+ + "\3\2\2\2\u0081\u0408\3\2\2\2\u0083\u040e\3\2\2\2\u0085\u0416\3\2\2\2\u0087"+ + "\u041b\3\2\2\2\u0089\u042e\3\2\2\2\u008b\u0441\3\2\2\2\u008d\u044f\3\2"+ + "\2\2\u008f\u0460\3\2\2\2\u0091\u046c\3\2\2\2\u0093\u0478\3\2\2\2\u0095"+ + "\u0488\3\2\2\2\u0097\u0493\3\2\2\2\u0099\u049e\3\2\2\2\u009b\u04a7\3\2"+ + "\2\2\u009d\u04b2\3\2\2\2\u009f\u04bc\3\2\2\2\u00a1\u04c3\3\2\2\2\u00a3"+ + "\u04cf\3\2\2\2\u00a5\u04d3\3\2\2\2\u00a7\u04db\3\2\2\2\u00a9\u04e2\3\2"+ + "\2\2\u00ab\u04e7\3\2\2\2\u00ad\u04ed\3\2\2\2\u00af\u04f4\3\2\2\2\u00b1"+ + "\u04fc\3\2\2\2\u00b3\u04fe\3\2\2\2\u00b5\u0500\3\2\2\2\u00b7\u0502\3\2"+ + "\2\2\u00b9\u0504\3\2\2\2\u00bb\u0506\3\2\2\2\u00bd\u0508\3\2\2\2\u00bf"+ + "\u050b\3\2\2\2\u00c1\u050e\3\2\2\2\u00c3\u0511\3\2\2\2\u00c5\u0513\3\2"+ + "\2\2\u00c7\u0515\3\2\2\2\u00c9\u0517\3\2\2\2\u00cb\u0519\3\2\2\2\u00cd"+ + "\u051b\3\2\2\2\u00cf\u051d\3\2\2\2\u00d1\u051f\3\2\2\2\u00d3\u0521\3\2"+ + "\2\2\u00d5\u0523\3\2\2\2\u00d7\u0525\3\2\2\2\u00d9\u0527\3\2\2\2\u00db"+ + "\u0529\3\2\2\2\u00dd\u052b\3\2\2\2\u00df\u052d\3\2\2\2\u00e1\u052f\3\2"+ + "\2\2\u00e3\u0531\3\2\2\2\u00e5\u0533\3\2\2\2\u00e7\u0537\3\2\2\2\u00e9"+ + "\u053d\3\2\2\2\u00eb\u054c\3\2\2\2\u00ed\u0552\3\2\2\2\u00ef\u055e\3\2"+ + "\2\2\u00f1\u0562\3\2\2\2\u00f3\u0567\3\2\2\2\u00f5\u056e\3\2\2\2\u00f7"+ + "\u0572\3\2\2\2\u00f9\u0577\3\2\2\2\u00fb\u057d\3\2\2\2\u00fd\u0583\3\2"+ + "\2\2\u00ff\u058a\3\2\2\2\u0101\u058e\3\2\2\2\u0103\u0594\3\2\2\2\u0105"+ + "\u059d\3\2\2\2\u0107\u05a5\3\2\2\2\u0109\u05b1\3\2\2\2\u010b\u05bc\3\2"+ + "\2\2\u010d\u05c7\3\2\2\2\u010f\u05cd\3\2\2\2\u0111\u05d2\3\2\2\2\u0113"+ + "\u05d7\3\2\2\2\u0115\u05de\3\2\2\2\u0117\u05e7\3\2\2\2\u0119\u05f5\3\2"+ + "\2\2\u011b\u05fc\3\2\2\2\u011d\u0608\3\2\2\2\u011f\u0610\3\2\2\2\u0121"+ + "\u0619\3\2\2\2\u0123\u0624\3\2\2\2\u0125\u062f\3\2\2\2\u0127\u0634\3\2"+ + "\2\2\u0129\u063e\3\2\2\2\u012b\u0640\3\2\2\2\u012d\u0643\3\2\2\2\u012f"+ + "\u0647\3\2\2\2\u0131\u064c\3\2\2\2\u0133\u0654\3\2\2\2\u0135\u0659\3\2"+ + "\2\2\u0137\u065f\3\2\2\2\u0139\u0661\3\2\2\2\u013b\u0665\3\2\2\2\u013d"+ + "\u066b\3\2\2\2\u013f\u066e\3\2\2\2\u0141\u0672\3\2\2\2\u0143\u0678\3\2"+ + "\2\2\u0145\u067d\3\2\2\2\u0147\u0681\3\2\2\2\u0149\u0684\3\2\2\2\u014b"+ + "\u0688\3\2\2\2\u014d\u068e\3\2\2\2\u014f\u0693\3\2\2\2\u0151\u0699\3\2"+ + "\2\2\u0153\u069e\3\2\2\2\u0155\u06a3\3\2\2\2\u0157\u06ac\3\2\2\2\u0159"+ + "\u06b1\3\2\2\2\u015b\u06b6\3\2\2\2\u015d\u06bb\3\2\2\2\u015f\u06c1\3\2"+ + "\2\2\u0161\u06c5\3\2\2\2\u0163\u06c9\3\2\2\2\u0165\u06d1\3\2\2\2\u0167"+ + "\u06d9\3\2\2\2\u0169\u06dd\3\2\2\2\u016b\u06e1\3\2\2\2\u016d\u06e9\3\2"+ + "\2\2\u016f\u06ee\3\2\2\2\u0171\u06f7\3\2\2\2\u0173\u0700\3\2\2\2\u0175"+ + "\u070b\3\2\2\2\u0177\u0715\3\2\2\2\u0179\u071f\3\2\2\2\u017b\u0727\3\2"+ + "\2\2\u017d\u0731\3\2\2\2\u017f\u073b\3\2\2\2\u0181\u0743\3\2\2\2\u0183"+ + "\u0748\3\2\2\2\u0185\u0754\3\2\2\2\u0187\u075e\3\2\2\2\u0189\u076a\3\2"+ + "\2\2\u018b\u0772\3\2\2\2\u018d\u0779\3\2\2\2\u018f\u0783\3\2\2\2\u0191"+ + "\u0789\3\2\2\2\u0193\u078f\3\2\2\2\u0195\u0794\3\2\2\2\u0197\u0797\3\2"+ + "\2\2\u0199\u079d\3\2\2\2\u019b\u07a3\3\2\2\2\u019d\u07aa\3\2\2\2\u019f"+ + "\u07b4\3\2\2\2\u01a1\u07bb\3\2\2\2\u01a3\u07c2\3\2\2\2\u01a5\u07c8\3\2"+ + "\2\2\u01a7\u07cd\3\2\2\2\u01a9\u07d3\3\2\2\2\u01ab\u07da\3\2\2\2\u01ad"+ + "\u07e2\3\2\2\2\u01af\u07e7\3\2\2\2\u01b1\u07ec\3\2\2\2\u01b3\u07f3\3\2"+ + "\2\2\u01b5\u07fd\3\2\2\2\u01b7\u0804\3\2\2\2\u01b9\u080b\3\2\2\2\u01bb"+ + "\u080e\3\2\2\2\u01bd\u0814\3\2\2\2\u01bf\u0821\3\2\2\2\u01c1\u0835\3\2"+ + "\2\2\u01c3\u084c\3\2\2\2\u01c5\u085d\3\2\2\2\u01c7\u0866\3\2\2\2\u01c9"+ + "\u088a\3\2\2\2\u01cb\u0890\3\2\2\2\u01cd\u08a1\3\2\2\2\u01cf\u08af\3\2"+ + "\2\2\u01d1\u08c0\3\2\2\2\u01d3\u08db\3\2\2\2\u01d5\u08e1\3\2\2\2\u01d7"+ + "\u08f6\3\2\2\2\u01d9\u090a\3\2\2\2\u01db\u091f\3\2\2\2\u01dd\u092d\3\2"+ + "\2\2\u01df\u0937\3\2\2\2\u01e1\u093f\3\2\2\2\u01e3\u0951\3\2\2\2\u01e5"+ + "\u0969\3\2\2\2\u01e7\u0978\3\2\2\2\u01e9\u098d\3\2\2\2\u01eb\u0996\3\2"+ + "\2\2\u01ed\u09a2\3\2\2\2\u01ef\u09b0\3\2\2\2\u01f1\u09bf\3\2\2\2\u01f3"+ + "\u09d2\3\2\2\2\u01f5\u09da\3\2\2\2\u01f7\u09df\3\2\2\2\u01f9\u09eb\3\2"+ + "\2\2\u01fb\u09f0\3\2\2\2\u01fd\u0a01\3\2\2\2\u01ff\u0a06\3\2\2\2\u0201"+ + "\u0a09\3\2\2\2\u0203\u0a0b\3\2\2\2\u0205\u0a0d\3\2\2\2\u0207\u0a0f\3\2"+ + "\2\2\u0209\u0a11\3\2\2\2\u020b\u0a13\3\2\2\2\u020d\u0a15\3\2\2\2\u020f"+ + "\u0a18\3\2\2\2\u0211\u0a21\3\2\2\2\u0213\u0a31\3\2\2\2\u0215\u0a35\3\2"+ + "\2\2\u0217\u0a3f\3\2\2\2\u0219\u0a42\3\2\2\2\u021b\u0a4f\3\2\2\2\u021d"+ + "\u0a5c\3\2\2\2\u021f\u0a69\3\2\2\2\u0221\u0a6b\3\2\2\2\u0223\u0224\7U"+ + "\2\2\u0224\u0225\7G\2\2\u0225\u0226\7C\2\2\u0226\u0227\7T\2\2\u0227\u0228"+ + "\7E\2\2\u0228\u0229\7J\2\2\u0229\4\3\2\2\2\u022a\u022b\7H\2\2\u022b\u022c"+ + "\7T\2\2\u022c\u022d\7Q\2\2\u022d\u022e\7O\2\2\u022e\6\3\2\2\2\u022f\u0230"+ + "\7Y\2\2\u0230\u0231\7J\2\2\u0231\u0232\7G\2\2\u0232\u0233\7T\2\2\u0233"+ + "\u0234\7G\2\2\u0234\b\3\2\2\2\u0235\u0236\7H\2\2\u0236\u0237\7K\2\2\u0237"+ + "\u0238\7G\2\2\u0238\u0239\7N\2\2\u0239\u023a\7F\2\2\u023a\u023b\7U\2\2"+ + "\u023b\n\3\2\2\2\u023c\u023d\7T\2\2\u023d\u023e\7G\2\2\u023e\u023f\7P"+ + "\2\2\u023f\u0240\7C\2\2\u0240\u0241\7O\2\2\u0241\u0242\7G\2\2\u0242\f"+ + "\3\2\2\2\u0243\u0244\7U\2\2\u0244\u0245\7V\2\2\u0245\u0246\7C\2\2\u0246"+ + "\u0247\7V\2\2\u0247\u0248\7U\2\2\u0248\16\3\2\2\2\u0249\u024a\7F\2\2\u024a"+ + "\u024b\7G\2\2\u024b\u024c\7F\2\2\u024c\u024d\7W\2\2\u024d\u024e\7R\2\2"+ + "\u024e\20\3\2\2\2\u024f\u0250\7U\2\2\u0250\u0251\7Q\2\2\u0251\u0252\7"+ + "T\2\2\u0252\u0253\7V\2\2\u0253\22\3\2\2\2\u0254\u0255\7G\2\2\u0255\u0256"+ + "\7X\2\2\u0256\u0257\7C\2\2\u0257\u0258\7N\2\2\u0258\24\3\2\2\2\u0259\u025a"+ + "\7J\2\2\u025a\u025b\7G\2\2\u025b\u025c\7C\2\2\u025c\u025d\7F\2\2\u025d"+ + "\26\3\2\2\2\u025e\u025f\7V\2\2\u025f\u0260\7Q\2\2\u0260\u0261\7R\2\2\u0261"+ + "\30\3\2\2\2\u0262\u0263\7T\2\2\u0263\u0264\7C\2\2\u0264\u0265\7T\2\2\u0265"+ + "\u0266\7G\2\2\u0266\32\3\2\2\2\u0267\u0268\7R\2\2\u0268\u0269\7C\2\2\u0269"+ + "\u026a\7T\2\2\u026a\u026b\7U\2\2\u026b\u026c\7G\2\2\u026c\34\3\2\2\2\u026d"+ + "\u026e\7M\2\2\u026e\u026f\7O\2\2\u026f\u0270\7G\2\2\u0270\u0271\7C\2\2"+ + "\u0271\u0272\7P\2\2\u0272\u0273\7U\2\2\u0273\36\3\2\2\2\u0274\u0275\7"+ + "C\2\2\u0275\u0276\7F\2\2\u0276 \3\2\2\2\u0277\u0278\7C\2\2\u0278\u0279"+ + "\7U\2\2\u0279\"\3\2\2\2\u027a\u027b\7D\2\2\u027b\u027c\7[\2\2\u027c$\3"+ + "\2\2\2\u027d\u027e\7U\2\2\u027e\u027f\7Q\2\2\u027f\u0280\7W\2\2\u0280"+ + "\u0281\7T\2\2\u0281\u0282\7E\2\2\u0282\u0283\7G\2\2\u0283&\3\2\2\2\u0284"+ + "\u0285\7K\2\2\u0285\u0286\7P\2\2\u0286\u0287\7F\2\2\u0287\u0288\7G\2\2"+ + "\u0288\u0289\7Z\2\2\u0289(\3\2\2\2\u028a\u028b\7F\2\2\u028b*\3\2\2\2\u028c"+ + "\u028d\7F\2\2\u028d\u028e\7G\2\2\u028e\u028f\7U\2\2\u028f\u0290\7E\2\2"+ + "\u0290,\3\2\2\2\u0291\u0292\7U\2\2\u0292\u0293\7Q\2\2\u0293\u0294\7T\2"+ + "\2\u0294\u0295\7V\2\2\u0295\u0296\7D\2\2\u0296\u0297\7[\2\2\u0297.\3\2"+ + "\2\2\u0298\u0299\7C\2\2\u0299\u029a\7W\2\2\u029a\u029b\7V\2\2\u029b\u029c"+ + "\7Q\2\2\u029c\60\3\2\2\2\u029d\u029e\7U\2\2\u029e\u029f\7V\2\2\u029f\u02a0"+ + "\7T\2\2\u02a0\62\3\2\2\2\u02a1\u02a2\7K\2\2\u02a2\u02a3\7R\2\2\u02a3\64"+ + "\3\2\2\2\u02a4\u02a5\7P\2\2\u02a5\u02a6\7W\2\2\u02a6\u02a7\7O\2\2\u02a7"+ + "\66\3\2\2\2\u02a8\u02a9\7M\2\2\u02a9\u02aa\7G\2\2\u02aa\u02ab\7G\2\2\u02ab"+ + "\u02ac\7R\2\2\u02ac\u02ad\7G\2\2\u02ad\u02ae\7O\2\2\u02ae\u02af\7R\2\2"+ + "\u02af\u02b0\7V\2\2\u02b0\u02b1\7[\2\2\u02b18\3\2\2\2\u02b2\u02b3\7E\2"+ + "\2\u02b3\u02b4\7Q\2\2\u02b4\u02b5\7P\2\2\u02b5\u02b6\7U\2\2\u02b6\u02b7"+ + "\7G\2\2\u02b7\u02b8\7E\2\2\u02b8\u02b9\7W\2\2\u02b9\u02ba\7V\2\2\u02ba"+ + "\u02bb\7K\2\2\u02bb\u02bc\7X\2\2\u02bc\u02bd\7G\2\2\u02bd:\3\2\2\2\u02be"+ + "\u02bf\7F\2\2\u02bf\u02c0\7G\2\2\u02c0\u02c1\7F\2\2\u02c1\u02c2\7W\2\2"+ + "\u02c2\u02c3\7R\2\2\u02c3\u02c4\7a\2\2\u02c4\u02c5\7U\2\2\u02c5\u02c6"+ + "\7R\2\2\u02c6\u02c7\7N\2\2\u02c7\u02c8\7K\2\2\u02c8\u02c9\7V\2\2\u02c9"+ + "\u02ca\7X\2\2\u02ca\u02cb\7C\2\2\u02cb\u02cc\7N\2\2\u02cc\u02cd\7W\2\2"+ + "\u02cd\u02ce\7G\2\2\u02ce\u02cf\7U\2\2\u02cf<\3\2\2\2\u02d0\u02d1\7R\2"+ + "\2\u02d1\u02d2\7C\2\2\u02d2\u02d3\7T\2\2\u02d3\u02d4\7V\2\2\u02d4\u02d5"+ + "\7K\2\2\u02d5\u02d6\7V\2\2\u02d6\u02d7\7K\2\2\u02d7\u02d8\7Q\2\2\u02d8"+ + "\u02d9\7P\2\2\u02d9\u02da\7U\2\2\u02da>\3\2\2\2\u02db\u02dc\7C\2\2\u02dc"+ + "\u02dd\7N\2\2\u02dd\u02de\7N\2\2\u02de\u02df\7P\2\2\u02df\u02e0\7W\2\2"+ + "\u02e0\u02e1\7O\2\2\u02e1@\3\2\2\2\u02e2\u02e3\7F\2\2\u02e3\u02e4\7G\2"+ + "\2\u02e4\u02e5\7N\2\2\u02e5\u02e6\7K\2\2\u02e6\u02e7\7O\2\2\u02e7B\3\2"+ + "\2\2\u02e8\u02e9\7E\2\2\u02e9\u02ea\7G\2\2\u02ea\u02eb\7P\2\2\u02eb\u02ec"+ + "\7V\2\2\u02ec\u02ed\7T\2\2\u02ed\u02ee\7Q\2\2\u02ee\u02ef\7K\2\2\u02ef"+ + "\u02f0\7F\2\2\u02f0\u02f1\7U\2\2\u02f1D\3\2\2\2\u02f2\u02f3\7K\2\2\u02f3"+ + "\u02f4\7V\2\2\u02f4\u02f5\7G\2\2\u02f5\u02f6\7T\2\2\u02f6\u02f7\7C\2\2"+ + "\u02f7\u02f8\7V\2\2\u02f8\u02f9\7K\2\2\u02f9\u02fa\7Q\2\2\u02fa\u02fb"+ + "\7P\2\2\u02fb\u02fc\7U\2\2\u02fcF\3\2\2\2\u02fd\u02fe\7F\2\2\u02fe\u02ff"+ + "\7K\2\2\u02ff\u0300\7U\2\2\u0300\u0301\7V\2\2\u0301\u0302\7C\2\2\u0302"+ + "\u0303\7P\2\2\u0303\u0304\7E\2\2\u0304\u0305\7G\2\2\u0305\u0306\7a\2\2"+ + "\u0306\u0307\7V\2\2\u0307\u0308\7[\2\2\u0308\u0309\7R\2\2\u0309\u030a"+ + "\7G\2\2\u030aH\3\2\2\2\u030b\u030c\7P\2\2\u030c\u030d\7W\2\2\u030d\u030e"+ + "\7O\2\2\u030e\u030f\7D\2\2\u030f\u0310\7G\2\2\u0310\u0311\7T\2\2\u0311"+ + "\u0312\7a\2\2\u0312\u0313\7Q\2\2\u0313\u0314\7H\2\2\u0314\u0315\7a\2\2"+ + "\u0315\u0316\7V\2\2\u0316\u0317\7T\2\2\u0317\u0318\7G\2\2\u0318\u0319"+ + "\7G\2\2\u0319\u031a\7U\2\2\u031aJ\3\2\2\2\u031b\u031c\7U\2\2\u031c\u031d"+ + "\7J\2\2\u031d\u031e\7K\2\2\u031e\u031f\7P\2\2\u031f\u0320\7I\2\2\u0320"+ + "\u0321\7N\2\2\u0321\u0322\7G\2\2\u0322\u0323\7a\2\2\u0323\u0324\7U\2\2"+ + "\u0324\u0325\7K\2\2\u0325\u0326\7\\\2\2\u0326\u0327\7G\2\2\u0327L\3\2"+ + "\2\2\u0328\u0329\7U\2\2\u0329\u032a\7C\2\2\u032a\u032b\7O\2\2\u032b\u032c"+ + "\7R\2\2\u032c\u032d\7N\2\2\u032d\u032e\7G\2\2\u032e\u032f\7a\2\2\u032f"+ + "\u0330\7U\2\2\u0330\u0331\7K\2\2\u0331\u0332\7\\\2\2\u0332\u0333\7G\2"+ + "\2\u0333N\3\2\2\2\u0334\u0335\7Q\2\2\u0335\u0336\7W\2\2\u0336\u0337\7"+ + "V\2\2\u0337\u0338\7R\2\2\u0338\u0339\7W\2\2\u0339\u033a\7V\2\2\u033a\u033b"+ + "\7a\2\2\u033b\u033c\7C\2\2\u033c\u033d\7H\2\2\u033d\u033e\7V\2\2\u033e"+ + "\u033f\7G\2\2\u033f\u0340\7T\2\2\u0340P\3\2\2\2\u0341\u0342\7V\2\2\u0342"+ + "\u0343\7K\2\2\u0343\u0344\7O\2\2\u0344\u0345\7G\2\2\u0345\u0346\7a\2\2"+ + "\u0346\u0347\7F\2\2\u0347\u0348\7G\2\2\u0348\u0349\7E\2\2\u0349\u034a"+ + "\7C\2\2\u034a\u034b\7[\2\2\u034bR\3\2\2\2\u034c\u034d\7C\2\2\u034d\u034e"+ + "\7P\2\2\u034e\u034f\7Q\2\2\u034f\u0350\7O\2\2\u0350\u0351\7C\2\2\u0351"+ + "\u0352\7N\2\2\u0352\u0353\7[\2\2\u0353\u0354\7a\2\2\u0354\u0355\7T\2\2"+ + "\u0355\u0356\7C\2\2\u0356\u0357\7V\2\2\u0357\u0358\7G\2\2\u0358T\3\2\2"+ + "\2\u0359\u035a\7V\2\2\u035a\u035b\7K\2\2\u035b\u035c\7O\2\2\u035c\u035d"+ + "\7G\2\2\u035d\u035e\7a\2\2\u035e\u035f\7H\2\2\u035f\u0360\7K\2\2\u0360"+ + "\u0361\7G\2\2\u0361\u0362\7N\2\2\u0362\u0363\7F\2\2\u0363V\3\2\2\2\u0364"+ + "\u0365\7V\2\2\u0365\u0366\7K\2\2\u0366\u0367\7O\2\2\u0367\u0368\7G\2\2"+ + "\u0368\u0369\7a\2\2\u0369\u036a\7\\\2\2\u036a\u036b\7Q\2\2\u036b\u036c"+ + "\7P\2\2\u036c\u036d\7G\2\2\u036dX\3\2\2\2\u036e\u036f\7V\2\2\u036f\u0370"+ + "\7T\2\2\u0370\u0371\7C\2\2\u0371\u0372\7K\2\2\u0372\u0373\7P\2\2\u0373"+ + "\u0374\7K\2\2\u0374\u0375\7P\2\2\u0375\u0376\7I\2\2\u0376\u0377\7a\2\2"+ + "\u0377\u0378\7F\2\2\u0378\u0379\7C\2\2\u0379\u037a\7V\2\2\u037a\u037b"+ + "\7C\2\2\u037b\u037c\7a\2\2\u037c\u037d\7U\2\2\u037d\u037e\7K\2\2\u037e"+ + "\u037f\7\\\2\2\u037f\u0380\7G\2\2\u0380Z\3\2\2\2\u0381\u0382\7C\2\2\u0382"+ + "\u0383\7P\2\2\u0383\u0384\7Q\2\2\u0384\u0385\7O\2\2\u0385\u0386\7C\2\2"+ + "\u0386\u0387\7N\2\2\u0387\u0388\7[\2\2\u0388\u0389\7a\2\2\u0389\u038a"+ + "\7U\2\2\u038a\u038b\7E\2\2\u038b\u038c\7Q\2\2\u038c\u038d\7T\2\2\u038d"+ + "\u038e\7G\2\2\u038e\u038f\7a\2\2\u038f\u0390\7V\2\2\u0390\u0391\7J\2\2"+ + "\u0391\u0392\7T\2\2\u0392\u0393\7G\2\2\u0393\u0394\7U\2\2\u0394\u0395"+ + "\7J\2\2\u0395\u0396\7Q\2\2\u0396\u0397\7N\2\2\u0397\u0398\7F\2\2\u0398"+ + "\\\3\2\2\2\u0399\u039a\7E\2\2\u039a\u039b\7C\2\2\u039b\u039c\7U\2\2\u039c"+ + "\u039d\7G\2\2\u039d^\3\2\2\2\u039e\u039f\7K\2\2\u039f\u03a0\7P\2\2\u03a0"+ + "`\3\2\2\2\u03a1\u03a2\7P\2\2\u03a2\u03a3\7Q\2\2\u03a3\u03a4\7V\2\2\u03a4"+ + "b\3\2\2\2\u03a5\u03a6\7Q\2\2\u03a6\u03a7\7T\2\2\u03a7d\3\2\2\2\u03a8\u03a9"+ + "\7C\2\2\u03a9\u03aa\7P\2\2\u03aa\u03ab\7F\2\2\u03abf\3\2\2\2\u03ac\u03ad"+ + "\7Z\2\2\u03ad\u03ae\7Q\2\2\u03ae\u03af\7T\2\2\u03afh\3\2\2\2\u03b0\u03b1"+ + "\7V\2\2\u03b1\u03b2\7T\2\2\u03b2\u03b3\7W\2\2\u03b3\u03b4\7G\2\2\u03b4"+ + "j\3\2\2\2\u03b5\u03b6\7H\2\2\u03b6\u03b7\7C\2\2\u03b7\u03b8\7N\2\2\u03b8"+ + "\u03b9\7U\2\2\u03b9\u03ba\7G\2\2\u03bal\3\2\2\2\u03bb\u03bc\7T\2\2\u03bc"+ + "\u03bd\7G\2\2\u03bd\u03be\7I\2\2\u03be\u03bf\7G\2\2\u03bf\u03c0\7Z\2\2"+ + "\u03c0\u03c1\7R\2\2\u03c1n\3\2\2\2\u03c2\u03c3\7F\2\2\u03c3\u03c4\7C\2"+ + "\2\u03c4\u03c5\7V\2\2\u03c5\u03c6\7G\2\2\u03c6\u03c7\7V\2\2\u03c7\u03c8"+ + "\7K\2\2\u03c8\u03c9\7O\2\2\u03c9\u03ca\7G\2\2\u03cap\3\2\2\2\u03cb\u03cc"+ + "\7K\2\2\u03cc\u03cd\7P\2\2\u03cd\u03ce\7V\2\2\u03ce\u03cf\7G\2\2\u03cf"+ + "\u03d0\7T\2\2\u03d0\u03d1\7X\2\2\u03d1\u03d2\7C\2\2\u03d2\u03d3\7N\2\2"+ + "\u03d3r\3\2\2\2\u03d4\u03d5\7O\2\2\u03d5\u03d6\7K\2\2\u03d6\u03d7\7E\2"+ + "\2\u03d7\u03d8\7T\2\2\u03d8\u03d9\7Q\2\2\u03d9\u03da\7U\2\2\u03da\u03db"+ + "\7G\2\2\u03db\u03dc\7E\2\2\u03dc\u03dd\7Q\2\2\u03dd\u03de\7P\2\2\u03de"+ + "\u03df\7F\2\2\u03dft\3\2\2\2\u03e0\u03e1\7O\2\2\u03e1\u03e2\7K\2\2\u03e2"+ + "\u03e3\7N\2\2\u03e3\u03e4\7N\2\2\u03e4\u03e5\7K\2\2\u03e5\u03e6\7U\2\2"+ + "\u03e6\u03e7\7G\2\2\u03e7\u03e8\7E\2\2\u03e8\u03e9\7Q\2\2\u03e9\u03ea"+ + "\7P\2\2\u03ea\u03eb\7F\2\2\u03ebv\3\2\2\2\u03ec\u03ed\7U\2\2\u03ed\u03ee"+ + "\7G\2\2\u03ee\u03ef\7E\2\2\u03ef\u03f0\7Q\2\2\u03f0\u03f1\7P\2\2\u03f1"+ + "\u03f2\7F\2\2\u03f2x\3\2\2\2\u03f3\u03f4\7O\2\2\u03f4\u03f5\7K\2\2\u03f5"+ + "\u03f6\7P\2\2\u03f6\u03f7\7W\2\2\u03f7\u03f8\7V\2\2\u03f8\u03f9\7G\2\2"+ + "\u03f9z\3\2\2\2\u03fa\u03fb\7J\2\2\u03fb\u03fc\7Q\2\2\u03fc\u03fd\7W\2"+ + "\2\u03fd\u03fe\7T\2\2\u03fe|\3\2\2\2\u03ff\u0400\7F\2\2\u0400\u0401\7"+ + "C\2\2\u0401\u0402\7[\2\2\u0402~\3\2\2\2\u0403\u0404\7Y\2\2\u0404\u0405"+ + "\7G\2\2\u0405\u0406\7G\2\2\u0406\u0407\7M\2\2\u0407\u0080\3\2\2\2\u0408"+ + "\u0409\7O\2\2\u0409\u040a\7Q\2\2\u040a\u040b\7P\2\2\u040b\u040c\7V\2\2"+ + "\u040c\u040d\7J\2\2\u040d\u0082\3\2\2\2\u040e\u040f\7S\2\2\u040f\u0410"+ + "\7W\2\2\u0410\u0411\7C\2\2\u0411\u0412\7T\2\2\u0412\u0413\7V\2\2\u0413"+ + "\u0414\7G\2\2\u0414\u0415\7T\2\2\u0415\u0084\3\2\2\2\u0416\u0417\7[\2"+ + "\2\u0417\u0418\7G\2\2\u0418\u0419\7C\2\2\u0419\u041a\7T\2\2\u041a\u0086"+ + "\3\2\2\2\u041b\u041c\7U\2\2\u041c\u041d\7G\2\2\u041d\u041e\7E\2\2\u041e"+ + "\u041f\7Q\2\2\u041f\u0420\7P\2\2\u0420\u0421\7F\2\2\u0421\u0422\7a\2\2"+ + "\u0422\u0423\7O\2\2\u0423\u0424\7K\2\2\u0424\u0425\7E\2\2\u0425\u0426"+ + "\7T\2\2\u0426\u0427\7Q\2\2\u0427\u0428\7U\2\2\u0428\u0429\7G\2\2\u0429"+ + "\u042a\7E\2\2\u042a\u042b\7Q\2\2\u042b\u042c\7P\2\2\u042c\u042d\7F\2\2"+ + "\u042d\u0088\3\2\2\2\u042e\u042f\7O\2\2\u042f\u0430\7K\2\2\u0430\u0431"+ + "\7P\2\2\u0431\u0432\7W\2\2\u0432\u0433\7V\2\2\u0433\u0434\7G\2\2\u0434"+ + "\u0435\7a\2\2\u0435\u0436\7O\2\2\u0436\u0437\7K\2\2\u0437\u0438\7E\2\2"+ + "\u0438\u0439\7T\2\2\u0439\u043a\7Q\2\2\u043a\u043b\7U\2\2\u043b\u043c"+ + "\7G\2\2\u043c\u043d\7E\2\2\u043d\u043e\7Q\2\2\u043e\u043f\7P\2\2\u043f"+ + "\u0440\7F\2\2\u0440\u008a\3\2\2\2\u0441\u0442\7O\2\2\u0442\u0443\7K\2"+ + "\2\u0443\u0444\7P\2\2\u0444\u0445\7W\2\2\u0445\u0446\7V\2\2\u0446\u0447"+ + "\7G\2\2\u0447\u0448\7a\2\2\u0448\u0449\7U\2\2\u0449\u044a\7G\2\2\u044a"+ + "\u044b\7E\2\2\u044b\u044c\7Q\2\2\u044c\u044d\7P\2\2\u044d\u044e\7F\2\2"+ + "\u044e\u008c\3\2\2\2\u044f\u0450\7J\2\2\u0450\u0451\7Q\2\2\u0451\u0452"+ + "\7W\2\2\u0452\u0453\7T\2\2\u0453\u0454\7a\2\2\u0454\u0455\7O\2\2\u0455"+ + "\u0456\7K\2\2\u0456\u0457\7E\2\2\u0457\u0458\7T\2\2\u0458\u0459\7Q\2\2"+ + "\u0459\u045a\7U\2\2\u045a\u045b\7G\2\2\u045b\u045c\7E\2\2\u045c\u045d"+ + "\7Q\2\2\u045d\u045e\7P\2\2\u045e\u045f\7F\2\2\u045f\u008e\3\2\2\2\u0460"+ + "\u0461\7J\2\2\u0461\u0462\7Q\2\2\u0462\u0463\7W\2\2\u0463\u0464\7T\2\2"+ + "\u0464\u0465\7a\2\2\u0465\u0466\7U\2\2\u0466\u0467\7G\2\2\u0467\u0468"+ + "\7E\2\2\u0468\u0469\7Q\2\2\u0469\u046a\7P\2\2\u046a\u046b\7F\2\2\u046b"+ + "\u0090\3\2\2\2\u046c\u046d\7J\2\2\u046d\u046e\7Q\2\2\u046e\u046f\7W\2"+ + "\2\u046f\u0470\7T\2\2\u0470\u0471\7a\2\2\u0471\u0472\7O\2\2\u0472\u0473"+ + "\7K\2\2\u0473\u0474\7P\2\2\u0474\u0475\7W\2\2\u0475\u0476\7V\2\2\u0476"+ + "\u0477\7G\2\2\u0477\u0092\3\2\2\2\u0478\u0479\7F\2\2\u0479\u047a\7C\2"+ + "\2\u047a\u047b\7[\2\2\u047b\u047c\7a\2\2\u047c\u047d\7O\2\2\u047d\u047e"+ + "\7K\2\2\u047e\u047f\7E\2\2\u047f\u0480\7T\2\2\u0480\u0481\7Q\2\2\u0481"+ + "\u0482\7U\2\2\u0482\u0483\7G\2\2\u0483\u0484\7E\2\2\u0484\u0485\7Q\2\2"+ + "\u0485\u0486\7P\2\2\u0486\u0487\7F\2\2\u0487\u0094\3\2\2\2\u0488\u0489"+ + "\7F\2\2\u0489\u048a\7C\2\2\u048a\u048b\7[\2\2\u048b\u048c\7a\2\2\u048c"+ + "\u048d\7U\2\2\u048d\u048e\7G\2\2\u048e\u048f\7E\2\2\u048f\u0490\7Q\2\2"+ + "\u0490\u0491\7P\2\2\u0491\u0492\7F\2\2\u0492\u0096\3\2\2\2\u0493\u0494"+ + "\7F\2\2\u0494\u0495\7C\2\2\u0495\u0496\7[\2\2\u0496\u0497\7a\2\2\u0497"+ + "\u0498\7O\2\2\u0498\u0499\7K\2\2\u0499\u049a\7P\2\2\u049a\u049b\7W\2\2"+ + "\u049b\u049c\7V\2\2\u049c\u049d\7G\2\2\u049d\u0098\3\2\2\2\u049e\u049f"+ + "\7F\2\2\u049f\u04a0\7C\2\2\u04a0\u04a1\7[\2\2\u04a1\u04a2\7a\2\2\u04a2"+ + "\u04a3\7J\2\2\u04a3\u04a4\7Q\2\2\u04a4\u04a5\7W\2\2\u04a5\u04a6\7T\2\2"+ + "\u04a6\u009a\3\2\2\2\u04a7\u04a8\7[\2\2\u04a8\u04a9\7G\2\2\u04a9\u04aa"+ + "\7C\2\2\u04aa\u04ab\7T\2\2\u04ab\u04ac\7a\2\2\u04ac\u04ad\7O\2\2\u04ad"+ + "\u04ae\7Q\2\2\u04ae\u04af\7P\2\2\u04af\u04b0\7V\2\2\u04b0\u04b1\7J\2\2"+ + "\u04b1\u009c\3\2\2\2\u04b2\u04b3\7F\2\2\u04b3\u04b4\7C\2\2\u04b4\u04b5"+ + "\7V\2\2\u04b5\u04b6\7C\2\2\u04b6\u04b7\7O\2\2\u04b7\u04b8\7Q\2\2\u04b8"+ + "\u04b9\7F\2\2\u04b9\u04ba\7G\2\2\u04ba\u04bb\7N\2\2\u04bb\u009e\3\2\2"+ + "\2\u04bc\u04bd\7N\2\2\u04bd\u04be\7Q\2\2\u04be\u04bf\7Q\2\2\u04bf\u04c0"+ + "\7M\2\2\u04c0\u04c1\7W\2\2\u04c1\u04c2\7R\2\2\u04c2\u00a0\3\2\2\2\u04c3"+ + "\u04c4\7U\2\2\u04c4\u04c5\7C\2\2\u04c5\u04c6\7X\2\2\u04c6\u04c7\7G\2\2"+ + "\u04c7\u04c8\7F\2\2\u04c8\u04c9\7U\2\2\u04c9\u04ca\7G\2\2\u04ca\u04cb"+ + "\7C\2\2\u04cb\u04cc\7T\2\2\u04cc\u04cd\7E\2\2\u04cd\u04ce\7J\2\2\u04ce"+ + "\u00a2\3\2\2\2\u04cf\u04d0\7K\2\2\u04d0\u04d1\7P\2\2\u04d1\u04d2\7V\2"+ + "\2\u04d2\u00a4\3\2\2\2\u04d3\u04d4\7K\2\2\u04d4\u04d5\7P\2\2\u04d5\u04d6"+ + "\7V\2\2\u04d6\u04d7\7G\2\2\u04d7\u04d8\7I\2\2\u04d8\u04d9\7G\2\2\u04d9"+ + "\u04da\7T\2\2\u04da\u00a6\3\2\2\2\u04db\u04dc\7F\2\2\u04dc\u04dd\7Q\2"+ + "\2\u04dd\u04de\7W\2\2\u04de\u04df\7D\2\2\u04df\u04e0\7N\2\2\u04e0\u04e1"+ + "\7G\2\2\u04e1\u00a8\3\2\2\2\u04e2\u04e3\7N\2\2\u04e3\u04e4\7Q\2\2\u04e4"+ + "\u04e5\7P\2\2\u04e5\u04e6\7I\2\2\u04e6\u00aa\3\2\2\2\u04e7\u04e8\7H\2"+ + "\2\u04e8\u04e9\7N\2\2\u04e9\u04ea\7Q\2\2\u04ea\u04eb\7C\2\2\u04eb\u04ec"+ + "\7V\2\2\u04ec\u00ac\3\2\2\2\u04ed\u04ee\7U\2\2\u04ee\u04ef\7V\2\2\u04ef"+ + "\u04f0\7T\2\2\u04f0\u04f1\7K\2\2\u04f1\u04f2\7P\2\2\u04f2\u04f3\7I\2\2"+ + "\u04f3\u00ae\3\2\2\2\u04f4\u04f5\7D\2\2\u04f5\u04f6\7Q\2\2\u04f6\u04f7"+ + "\7Q\2\2\u04f7\u04f8\7N\2\2\u04f8\u04f9\7G\2\2\u04f9\u04fa\7C\2\2\u04fa"+ + "\u04fb\7P\2\2\u04fb\u00b0\3\2\2\2\u04fc\u04fd\7~\2\2\u04fd\u00b2\3\2\2"+ + "\2\u04fe\u04ff\7.\2\2\u04ff\u00b4\3\2\2\2\u0500\u0501\7\60\2\2\u0501\u00b6"+ + "\3\2\2\2\u0502\u0503\7?\2\2\u0503\u00b8\3\2\2\2\u0504\u0505\7@\2\2\u0505"+ + "\u00ba\3\2\2\2\u0506\u0507\7>\2\2\u0507\u00bc\3\2\2\2\u0508\u0509\7>\2"+ + "\2\u0509\u050a\7?\2\2\u050a\u00be\3\2\2\2\u050b\u050c\7@\2\2\u050c\u050d"+ + "\7?\2\2\u050d\u00c0\3\2\2\2\u050e\u050f\7#\2\2\u050f\u0510\7?\2\2\u0510"+ + "\u00c2\3\2\2\2\u0511\u0512\7-\2\2\u0512\u00c4\3\2\2\2\u0513\u0514\7/\2"+ + "\2\u0514\u00c6\3\2\2\2\u0515\u0516\7,\2\2\u0516\u00c8\3\2\2\2\u0517\u0518"+ + "\7\61\2\2\u0518\u00ca\3\2\2\2\u0519\u051a\7\'\2\2\u051a\u00cc\3\2\2\2"+ + "\u051b\u051c\7#\2\2\u051c\u00ce\3\2\2\2\u051d\u051e\7<\2\2\u051e\u00d0"+ + "\3\2\2\2\u051f\u0520\7*\2\2\u0520\u00d2\3\2\2\2\u0521\u0522\7+\2\2\u0522"+ + "\u00d4\3\2\2\2\u0523\u0524\7]\2\2\u0524\u00d6\3\2\2\2\u0525\u0526\7_\2"+ + "\2\u0526\u00d8\3\2\2\2\u0527\u0528\7)\2\2\u0528\u00da\3\2\2\2\u0529\u052a"+ + "\7$\2\2\u052a\u00dc\3\2\2\2\u052b\u052c\7b\2\2\u052c\u00de\3\2\2\2\u052d"+ + "\u052e\7\u0080\2\2\u052e\u00e0\3\2\2\2\u052f\u0530\7(\2\2\u0530\u00e2"+ + "\3\2\2\2\u0531\u0532\7`\2\2\u0532\u00e4\3\2\2\2\u0533\u0534\7C\2\2\u0534"+ + "\u0535\7X\2\2\u0535\u0536\7I\2\2\u0536\u00e6\3\2\2\2\u0537\u0538\7E\2"+ + "\2\u0538\u0539\7Q\2\2\u0539\u053a\7W\2\2\u053a\u053b\7P\2\2\u053b\u053c"+ + "\7V\2\2\u053c\u00e8\3\2\2\2\u053d\u053e\7F\2\2\u053e\u053f\7K\2\2\u053f"+ + "\u0540\7U\2\2\u0540\u0541\7V\2\2\u0541\u0542\7K\2\2\u0542\u0543\7P\2\2"+ + "\u0543\u0544\7E\2\2\u0544\u0545\7V\2\2\u0545\u0546\7a\2\2\u0546\u0547"+ + "\7E\2\2\u0547\u0548\7Q\2\2\u0548\u0549\7W\2\2\u0549\u054a\7P\2\2\u054a"+ + "\u054b\7V\2\2\u054b\u00ea\3\2\2\2\u054c\u054d\7G\2\2\u054d\u054e\7U\2"+ + "\2\u054e\u054f\7V\2\2\u054f\u0550\7F\2\2\u0550\u0551\7E\2\2\u0551\u00ec"+ + "\3\2\2\2\u0552\u0553\7G\2\2\u0553\u0554\7U\2\2\u0554\u0555\7V\2\2\u0555"+ + "\u0556\7F\2\2\u0556\u0557\7E\2\2\u0557\u0558\7a\2\2\u0558\u0559\7G\2\2"+ + "\u0559\u055a\7T\2\2\u055a\u055b\7T\2\2\u055b\u055c\7Q\2\2\u055c\u055d"+ + "\7T\2\2\u055d\u00ee\3\2\2\2\u055e\u055f\7O\2\2\u055f\u0560\7C\2\2\u0560"+ + "\u0561\7Z\2\2\u0561\u00f0\3\2\2\2\u0562\u0563\7O\2\2\u0563\u0564\7G\2"+ + "\2\u0564\u0565\7C\2\2\u0565\u0566\7P\2\2\u0566\u00f2\3\2\2\2\u0567\u0568"+ + "\7O\2\2\u0568\u0569\7G\2\2\u0569\u056a\7F\2\2\u056a\u056b\7K\2\2\u056b"+ + "\u056c\7C\2\2\u056c\u056d\7P\2\2\u056d\u00f4\3\2\2\2\u056e\u056f\7O\2"+ + "\2\u056f\u0570\7K\2\2\u0570\u0571\7P\2\2\u0571\u00f6\3\2\2\2\u0572\u0573"+ + "\7O\2\2\u0573\u0574\7Q\2\2\u0574\u0575\7F\2\2\u0575\u0576\7G\2\2\u0576"+ + "\u00f8\3\2\2\2\u0577\u0578\7T\2\2\u0578\u0579\7C\2\2\u0579\u057a\7P\2"+ + "\2\u057a\u057b\7I\2\2\u057b\u057c\7G\2\2\u057c\u00fa\3\2\2\2\u057d\u057e"+ + "\7U\2\2\u057e\u057f\7V\2\2\u057f\u0580\7F\2\2\u0580\u0581\7G\2\2\u0581"+ + "\u0582\7X\2\2\u0582\u00fc\3\2\2\2\u0583\u0584\7U\2\2\u0584\u0585\7V\2"+ + "\2\u0585\u0586\7F\2\2\u0586\u0587\7G\2\2\u0587\u0588\7X\2\2\u0588\u0589"+ + "\7R\2\2\u0589\u00fe\3\2\2\2\u058a\u058b\7U\2\2\u058b\u058c\7W\2\2\u058c"+ + "\u058d\7O\2\2\u058d\u0100\3\2\2\2\u058e\u058f\7U\2\2\u058f\u0590\7W\2"+ + "\2\u0590\u0591\7O\2\2\u0591\u0592\7U\2\2\u0592\u0593\7S\2\2\u0593\u0102"+ + "\3\2\2\2\u0594\u0595\7X\2\2\u0595\u0596\7C\2\2\u0596\u0597\7T\2\2\u0597"+ + "\u0598\7a\2\2\u0598\u0599\7U\2\2\u0599\u059a\7C\2\2\u059a\u059b\7O\2\2"+ + "\u059b\u059c\7R\2\2\u059c\u0104\3\2\2\2\u059d\u059e\7X\2\2\u059e\u059f"+ + "\7C\2\2\u059f\u05a0\7T\2\2\u05a0\u05a1\7a\2\2\u05a1\u05a2\7R\2\2\u05a2"+ + "\u05a3\7Q\2\2\u05a3\u05a4\7R\2\2\u05a4\u0106\3\2\2\2\u05a5\u05a6\7U\2"+ + "\2\u05a6\u05a7\7V\2\2\u05a7\u05a8\7F\2\2\u05a8\u05a9\7F\2\2\u05a9\u05aa"+ + "\7G\2\2\u05aa\u05ab\7X\2\2\u05ab\u05ac\7a\2\2\u05ac\u05ad\7U\2\2\u05ad"+ + "\u05ae\7C\2\2\u05ae\u05af\7O\2\2\u05af\u05b0\7R\2\2\u05b0\u0108\3\2\2"+ + "\2\u05b1\u05b2\7U\2\2\u05b2\u05b3\7V\2\2\u05b3\u05b4\7F\2\2\u05b4\u05b5"+ + "\7F\2\2\u05b5\u05b6\7G\2\2\u05b6\u05b7\7X\2\2\u05b7\u05b8\7a\2\2\u05b8"+ + "\u05b9\7R\2\2\u05b9\u05ba\7Q\2\2\u05ba\u05bb\7R\2\2\u05bb\u010a\3\2\2"+ + "\2\u05bc\u05bd\7R\2\2\u05bd\u05be\7G\2\2\u05be\u05bf\7T\2\2\u05bf\u05c0"+ + "\7E\2\2\u05c0\u05c1\7G\2\2\u05c1\u05c2\7P\2\2\u05c2\u05c3\7V\2\2\u05c3"+ + "\u05c4\7K\2\2\u05c4\u05c5\7N\2\2\u05c5\u05c6\7G\2\2\u05c6\u010c\3\2\2"+ + "\2\u05c7\u05c8\7H\2\2\u05c8\u05c9\7K\2\2\u05c9\u05ca\7T\2\2\u05ca\u05cb"+ + "\7U\2\2\u05cb\u05cc\7V\2\2\u05cc\u010e\3\2\2\2\u05cd\u05ce\7N\2\2\u05ce"+ + "\u05cf\7C\2\2\u05cf\u05d0\7U\2\2\u05d0\u05d1\7V\2\2\u05d1\u0110\3\2\2"+ + "\2\u05d2\u05d3\7N\2\2\u05d3\u05d4\7K\2\2\u05d4\u05d5\7U\2\2\u05d5\u05d6"+ + "\7V\2\2\u05d6\u0112\3\2\2\2\u05d7\u05d8\7X\2\2\u05d8\u05d9\7C\2\2\u05d9"+ + "\u05da\7N\2\2\u05da\u05db\7W\2\2\u05db\u05dc\7G\2\2\u05dc\u05dd\7U\2\2"+ + "\u05dd\u0114\3\2\2\2\u05de\u05df\7G\2\2\u05df\u05e0\7C\2\2\u05e0\u05e1"+ + "\7T\2\2\u05e1\u05e2\7N\2\2\u05e2\u05e3\7K\2\2\u05e3\u05e4\7G\2\2\u05e4"+ + "\u05e5\7U\2\2\u05e5\u05e6\7V\2\2\u05e6\u0116\3\2\2\2\u05e7\u05e8\7G\2"+ + "\2\u05e8\u05e9\7C\2\2\u05e9\u05ea\7T\2\2\u05ea\u05eb\7N\2\2\u05eb\u05ec"+ + "\7K\2\2\u05ec\u05ed\7G\2\2\u05ed\u05ee\7U\2\2\u05ee\u05ef\7V\2\2\u05ef"+ + "\u05f0\7a\2\2\u05f0\u05f1\7V\2\2\u05f1\u05f2\7K\2\2\u05f2\u05f3\7O\2\2"+ + "\u05f3\u05f4\7G\2\2\u05f4\u0118\3\2\2\2\u05f5\u05f6\7N\2\2\u05f6\u05f7"+ + "\7C\2\2\u05f7\u05f8\7V\2\2\u05f8\u05f9\7G\2\2\u05f9\u05fa\7U\2\2\u05fa"+ + "\u05fb\7V\2\2\u05fb\u011a\3\2\2\2\u05fc\u05fd\7N\2\2\u05fd\u05fe\7C\2"+ + "\2\u05fe\u05ff\7V\2\2\u05ff\u0600\7G\2\2\u0600\u0601\7U\2\2\u0601\u0602"+ + "\7V\2\2\u0602\u0603\7a\2\2\u0603\u0604\7V\2\2\u0604\u0605\7K\2\2\u0605"+ + "\u0606\7O\2\2\u0606\u0607\7G\2\2\u0607\u011c\3\2\2\2\u0608\u0609\7R\2"+ + "\2\u0609\u060a\7G\2\2\u060a\u060b\7T\2\2\u060b\u060c\7a\2\2\u060c\u060d"+ + "\7F\2\2\u060d\u060e\7C\2\2\u060e\u060f\7[\2\2\u060f\u011e\3\2\2\2\u0610"+ + "\u0611\7R\2\2\u0611\u0612\7G\2\2\u0612\u0613\7T\2\2\u0613\u0614\7a\2\2"+ + "\u0614\u0615\7J\2\2\u0615\u0616\7Q\2\2\u0616\u0617\7W\2\2\u0617\u0618"+ + "\7T\2\2\u0618\u0120\3\2\2\2\u0619\u061a\7R\2\2\u061a\u061b\7G\2\2\u061b"+ + "\u061c\7T\2\2\u061c\u061d\7a\2\2\u061d\u061e\7O\2\2\u061e\u061f\7K\2\2"+ + "\u061f\u0620\7P\2\2\u0620\u0621\7W\2\2\u0621\u0622\7V\2\2\u0622\u0623"+ + "\7G\2\2\u0623\u0122\3\2\2\2\u0624\u0625\7R\2\2\u0625\u0626\7G\2\2\u0626"+ + "\u0627\7T\2\2\u0627\u0628\7a\2\2\u0628\u0629\7U\2\2\u0629\u062a\7G\2\2"+ + "\u062a\u062b\7E\2\2\u062b\u062c\7Q\2\2\u062c\u062d\7P\2\2\u062d\u062e"+ + "\7F\2\2\u062e\u0124\3\2\2\2\u062f\u0630\7T\2\2\u0630\u0631\7C\2\2\u0631"+ + "\u0632\7V\2\2\u0632\u0633\7G\2\2\u0633\u0126\3\2\2\2\u0634\u0635\7U\2"+ + "\2\u0635\u0636\7R\2\2\u0636\u0637\7C\2\2\u0637\u0638\7T\2\2\u0638\u0639"+ + "\7M\2\2\u0639\u063a\7N\2\2\u063a\u063b\7K\2\2\u063b\u063c\7P\2\2\u063c"+ + "\u063d\7G\2\2\u063d\u0128\3\2\2\2\u063e\u063f\7E\2\2\u063f\u012a\3\2\2"+ + "\2\u0640\u0641\7F\2\2\u0641\u0642\7E\2\2\u0642\u012c\3\2\2\2\u0643\u0644"+ + "\7C\2\2\u0644\u0645\7D\2\2\u0645\u0646\7U\2\2\u0646\u012e\3\2\2\2\u0647"+ + "\u0648\7E\2\2\u0648\u0649\7G\2\2\u0649\u064a\7K\2\2\u064a\u064b\7N\2\2"+ + "\u064b\u0130\3\2\2\2\u064c\u064d\7E\2\2\u064d\u064e\7G\2\2\u064e\u064f"+ + "\7K\2\2\u064f\u0650\7N\2\2\u0650\u0651\7K\2\2\u0651\u0652\7P\2\2\u0652"+ + "\u0653\7I\2\2\u0653\u0132\3\2\2\2\u0654\u0655\7E\2\2\u0655\u0656\7Q\2"+ + "\2\u0656\u0657\7P\2\2\u0657\u0658\7X\2\2\u0658\u0134\3\2\2\2\u0659\u065a"+ + "\7E\2\2\u065a\u065b\7T\2\2\u065b\u065c\7E\2\2\u065c\u065d\7\65\2\2\u065d"+ + "\u065e\7\64\2\2\u065e\u0136\3\2\2\2\u065f\u0660\7G\2\2\u0660\u0138\3\2"+ + "\2\2\u0661\u0662\7G\2\2\u0662\u0663\7Z\2\2\u0663\u0664\7R\2\2\u0664\u013a"+ + "\3\2\2\2\u0665\u0666\7H\2\2\u0666\u0667\7N\2\2\u0667\u0668\7Q\2\2\u0668"+ + "\u0669\7Q\2\2\u0669\u066a\7T\2\2\u066a\u013c\3\2\2\2\u066b\u066c\7N\2"+ + "\2\u066c\u066d\7P\2\2\u066d\u013e\3\2\2\2\u066e\u066f\7N\2\2\u066f\u0670"+ + "\7Q\2\2\u0670\u0671\7I\2\2\u0671\u0140\3\2\2\2\u0672\u0673\7N\2\2\u0673"+ + "\u0674\7Q\2\2\u0674\u0675\7I\2\2\u0675\u0676\7\63\2\2\u0676\u0677\7\62"+ + "\2\2\u0677\u0142\3\2\2\2\u0678\u0679\7N\2\2\u0679\u067a\7Q\2\2\u067a\u067b"+ + "\7I\2\2\u067b\u067c\7\64\2\2\u067c\u0144\3\2\2\2\u067d\u067e\7O\2\2\u067e"+ + "\u067f\7Q\2\2\u067f\u0680\7F\2\2\u0680\u0146\3\2\2\2\u0681\u0682\7R\2"+ + "\2\u0682\u0683\7K\2\2\u0683\u0148\3\2\2\2\u0684\u0685\7R\2\2\u0685\u0686"+ + "\7Q\2\2\u0686\u0687\7Y\2\2\u0687\u014a\3\2\2\2\u0688\u0689\7R\2\2\u0689"+ + "\u068a\7Q\2\2\u068a\u068b\7Y\2\2\u068b\u068c\7G\2\2\u068c\u068d\7T\2\2"+ + "\u068d\u014c\3\2\2\2\u068e\u068f\7T\2\2\u068f\u0690\7C\2\2\u0690\u0691"+ + "\7P\2\2\u0691\u0692\7F\2\2\u0692\u014e\3\2\2\2\u0693\u0694\7T\2\2\u0694"+ + "\u0695\7Q\2\2\u0695\u0696\7W\2\2\u0696\u0697\7P\2\2\u0697\u0698\7F\2\2"+ + "\u0698\u0150\3\2\2\2\u0699\u069a\7U\2\2\u069a\u069b\7K\2\2\u069b\u069c"+ + "\7I\2\2\u069c\u069d\7P\2\2\u069d\u0152\3\2\2\2\u069e\u069f\7U\2\2\u069f"+ + "\u06a0\7S\2\2\u06a0\u06a1\7T\2\2\u06a1\u06a2\7V\2\2\u06a2\u0154\3\2\2"+ + "\2\u06a3\u06a4\7V\2\2\u06a4\u06a5\7T\2\2\u06a5\u06a6\7W\2\2\u06a6\u06a7"+ + "\7P\2\2\u06a7\u06a8\7E\2\2\u06a8\u06a9\7C\2\2\u06a9\u06aa\7V\2\2\u06aa"+ + "\u06ab\7G\2\2\u06ab\u0156\3\2\2\2\u06ac\u06ad\7C\2\2\u06ad\u06ae\7E\2"+ + "\2\u06ae\u06af\7Q\2\2\u06af\u06b0\7U\2\2\u06b0\u0158\3\2\2\2\u06b1\u06b2"+ + "\7C\2\2\u06b2\u06b3\7U\2\2\u06b3\u06b4\7K\2\2\u06b4\u06b5\7P\2\2\u06b5"+ + "\u015a\3\2\2\2\u06b6\u06b7\7C\2\2\u06b7\u06b8\7V\2\2\u06b8\u06b9\7C\2"+ + "\2\u06b9\u06ba\7P\2\2\u06ba\u015c\3\2\2\2\u06bb\u06bc\7C\2\2\u06bc\u06bd"+ + "\7V\2\2\u06bd\u06be\7C\2\2\u06be\u06bf\7P\2\2\u06bf\u06c0\7\64\2\2\u06c0"+ + "\u015e\3\2\2\2\u06c1\u06c2\7E\2\2\u06c2\u06c3\7Q\2\2\u06c3\u06c4\7U\2"+ + "\2\u06c4\u0160\3\2\2\2\u06c5\u06c6\7E\2\2\u06c6\u06c7\7Q\2\2\u06c7\u06c8"+ + "\7V\2\2\u06c8\u0162\3\2\2\2\u06c9\u06ca\7F\2\2\u06ca\u06cb\7G\2\2\u06cb"+ + "\u06cc\7I\2\2\u06cc\u06cd\7T\2\2\u06cd\u06ce\7G\2\2\u06ce\u06cf\7G\2\2"+ + "\u06cf\u06d0\7U\2\2\u06d0\u0164\3\2\2\2\u06d1\u06d2\7T\2\2\u06d2\u06d3"+ + "\7C\2\2\u06d3\u06d4\7F\2\2\u06d4\u06d5\7K\2\2\u06d5\u06d6\7C\2\2\u06d6"+ + "\u06d7\7P\2\2\u06d7\u06d8\7U\2\2\u06d8\u0166\3\2\2\2\u06d9\u06da\7U\2"+ + "\2\u06da\u06db\7K\2\2\u06db\u06dc\7P\2\2\u06dc\u0168\3\2\2\2\u06dd\u06de"+ + "\7V\2\2\u06de\u06df\7C\2\2\u06df\u06e0\7P\2\2\u06e0\u016a\3\2\2\2\u06e1"+ + "\u06e2\7C\2\2\u06e2\u06e3\7F\2\2\u06e3\u06e4\7F\2\2\u06e4\u06e5\7F\2\2"+ + "\u06e5\u06e6\7C\2\2\u06e6\u06e7\7V\2\2\u06e7\u06e8\7G\2\2\u06e8\u016c"+ + "\3\2\2\2\u06e9\u06ea\7F\2\2\u06ea\u06eb\7C\2\2\u06eb\u06ec\7V\2\2\u06ec"+ + "\u06ed\7G\2\2\u06ed\u016e\3\2\2\2\u06ee\u06ef\7F\2\2\u06ef\u06f0\7C\2"+ + "\2\u06f0\u06f1\7V\2\2\u06f1\u06f2\7G\2\2\u06f2\u06f3\7a\2\2\u06f3\u06f4"+ + "\7C\2\2\u06f4\u06f5\7F\2\2\u06f5\u06f6\7F\2\2\u06f6\u0170\3\2\2\2\u06f7"+ + "\u06f8\7F\2\2\u06f8\u06f9\7C\2\2\u06f9\u06fa\7V\2\2\u06fa\u06fb\7G\2\2"+ + "\u06fb\u06fc\7a\2\2\u06fc\u06fd\7U\2\2\u06fd\u06fe\7W\2\2\u06fe\u06ff"+ + "\7D\2\2\u06ff\u0172\3\2\2\2\u0700\u0701\7F\2\2\u0701\u0702\7C\2\2\u0702"+ + "\u0703\7[\2\2\u0703\u0704\7Q\2\2\u0704\u0705\7H\2\2\u0705\u0706\7O\2\2"+ + "\u0706\u0707\7Q\2\2\u0707\u0708\7P\2\2\u0708\u0709\7V\2\2\u0709\u070a"+ + "\7J\2\2\u070a\u0174\3\2\2\2\u070b\u070c\7F\2\2\u070c\u070d\7C\2\2\u070d"+ + "\u070e\7[\2\2\u070e\u070f\7Q\2\2\u070f\u0710\7H\2\2\u0710\u0711\7Y\2\2"+ + "\u0711\u0712\7G\2\2\u0712\u0713\7G\2\2\u0713\u0714\7M\2\2\u0714\u0176"+ + "\3\2\2\2\u0715\u0716\7F\2\2\u0716\u0717\7C\2\2\u0717\u0718\7[\2\2\u0718"+ + "\u0719\7Q\2\2\u0719\u071a\7H\2\2\u071a\u071b\7[\2\2\u071b\u071c\7G\2\2"+ + "\u071c\u071d\7C\2\2\u071d\u071e\7T\2\2\u071e\u0178\3\2\2\2\u071f\u0720"+ + "\7F\2\2\u0720\u0721\7C\2\2\u0721\u0722\7[\2\2\u0722\u0723\7P\2\2\u0723"+ + "\u0724\7C\2\2\u0724\u0725\7O\2\2\u0725\u0726\7G\2\2\u0726\u017a\3\2\2"+ + "\2\u0727\u0728\7H\2\2\u0728\u0729\7T\2\2\u0729\u072a\7Q\2\2\u072a\u072b"+ + "\7O\2\2\u072b\u072c\7a\2\2\u072c\u072d\7F\2\2\u072d\u072e\7C\2\2\u072e"+ + "\u072f\7[\2\2\u072f\u0730\7U\2\2\u0730\u017c\3\2\2\2\u0731\u0732\7O\2"+ + "\2\u0732\u0733\7Q\2\2\u0733\u0734\7P\2\2\u0734\u0735\7V\2\2\u0735\u0736"+ + "\7J\2\2\u0736\u0737\7P\2\2\u0737\u0738\7C\2\2\u0738\u0739\7O\2\2\u0739"+ + "\u073a\7G\2\2\u073a\u017e\3\2\2\2\u073b\u073c\7U\2\2\u073c\u073d\7W\2"+ + "\2\u073d\u073e\7D\2\2\u073e\u073f\7F\2\2\u073f\u0740\7C\2\2\u0740\u0741"+ + "\7V\2\2\u0741\u0742\7G\2\2\u0742\u0180\3\2\2\2\u0743\u0744\7V\2\2\u0744"+ + "\u0745\7K\2\2\u0745\u0746\7O\2\2\u0746\u0747\7G\2\2\u0747\u0182\3\2\2"+ + "\2\u0748\u0749\7V\2\2\u0749\u074a\7K\2\2\u074a\u074b\7O\2\2\u074b\u074c"+ + "\7G\2\2\u074c\u074d\7a\2\2\u074d\u074e\7V\2\2\u074e\u074f\7Q\2\2\u074f"+ + "\u0750\7a\2\2\u0750\u0751\7U\2\2\u0751\u0752\7G\2\2\u0752\u0753\7E\2\2"+ + "\u0753\u0184\3\2\2\2\u0754\u0755\7V\2\2\u0755\u0756\7K\2\2\u0756\u0757"+ + "\7O\2\2\u0757\u0758\7G\2\2\u0758\u0759\7U\2\2\u0759\u075a\7V\2\2\u075a"+ + "\u075b\7C\2\2\u075b\u075c\7O\2\2\u075c\u075d\7R\2\2\u075d\u0186\3\2\2"+ + "\2\u075e\u075f\7F\2\2\u075f\u0760\7C\2\2\u0760\u0761\7V\2\2\u0761\u0762"+ + "\7G\2\2\u0762\u0763\7a\2\2\u0763\u0764\7H\2\2\u0764\u0765\7Q\2\2\u0765"+ + "\u0766\7T\2\2\u0766\u0767\7O\2\2\u0767\u0768\7C\2\2\u0768\u0769\7V\2\2"+ + "\u0769\u0188\3\2\2\2\u076a\u076b\7V\2\2\u076b\u076c\7Q\2\2\u076c\u076d"+ + "\7a\2\2\u076d\u076e\7F\2\2\u076e\u076f\7C\2\2\u076f\u0770\7[\2\2\u0770"+ + "\u0771\7U\2\2\u0771\u018a\3\2\2\2\u0772\u0773\7U\2\2\u0773\u0774\7W\2"+ + "\2\u0774\u0775\7D\2\2\u0775\u0776\7U\2\2\u0776\u0777\7V\2\2\u0777\u0778"+ + "\7T\2\2\u0778\u018c\3\2\2\2\u0779\u077a\7U\2\2\u077a\u077b\7W\2\2\u077b"+ + "\u077c\7D\2\2\u077c\u077d\7U\2\2\u077d\u077e\7V\2\2\u077e\u077f\7T\2\2"+ + "\u077f\u0780\7K\2\2\u0780\u0781\7P\2\2\u0781\u0782\7I\2\2\u0782\u018e"+ + "\3\2\2\2\u0783\u0784\7N\2\2\u0784\u0785\7V\2\2\u0785\u0786\7T\2\2\u0786"+ + "\u0787\7K\2\2\u0787\u0788\7O\2\2\u0788\u0190\3\2\2\2\u0789\u078a\7T\2"+ + "\2\u078a\u078b\7V\2\2\u078b\u078c\7T\2\2\u078c\u078d\7K\2\2\u078d\u078e"+ + "\7O\2\2\u078e\u0192\3\2\2\2\u078f\u0790\7V\2\2\u0790\u0791\7T\2\2\u0791"+ + "\u0792\7K\2\2\u0792\u0793\7O\2\2\u0793\u0194\3\2\2\2\u0794\u0795\7V\2"+ + "\2\u0795\u0796\7Q\2\2\u0796\u0196\3\2\2\2\u0797\u0798\7N\2\2\u0798\u0799"+ + "\7Q\2\2\u0799\u079a\7Y\2\2\u079a\u079b\7G\2\2\u079b\u079c\7T\2\2\u079c"+ + "\u0198\3\2\2\2\u079d\u079e\7W\2\2\u079e\u079f\7R\2\2\u079f\u07a0\7R\2"+ + "\2\u07a0\u07a1\7G\2\2\u07a1\u07a2\7T\2\2\u07a2\u019a\3\2\2\2\u07a3\u07a4"+ + "\7E\2\2\u07a4\u07a5\7Q\2\2\u07a5\u07a6\7P\2\2\u07a6\u07a7\7E\2\2\u07a7"+ + "\u07a8\7C\2\2\u07a8\u07a9\7V\2\2\u07a9\u019c\3\2\2\2\u07aa\u07ab\7E\2"+ + "\2\u07ab\u07ac\7Q\2\2\u07ac\u07ad\7P\2\2\u07ad\u07ae\7E\2\2\u07ae\u07af"+ + "\7C\2\2\u07af\u07b0\7V\2\2\u07b0\u07b1\7a\2\2\u07b1\u07b2\7Y\2\2\u07b2"+ + "\u07b3\7U\2\2\u07b3\u019e\3\2\2\2\u07b4\u07b5\7N\2\2\u07b5\u07b6\7G\2"+ + "\2\u07b6\u07b7\7P\2\2\u07b7\u07b8\7I\2\2\u07b8\u07b9\7V\2\2\u07b9\u07ba"+ + "\7J\2\2\u07ba\u01a0\3\2\2\2\u07bb\u07bc\7U\2\2\u07bc\u07bd\7V\2\2\u07bd"+ + "\u07be\7T\2\2\u07be\u07bf\7E\2\2\u07bf\u07c0\7O\2\2\u07c0\u07c1\7R\2\2"+ + "\u07c1\u01a2\3\2\2\2\u07c2\u07c3\7T\2\2\u07c3\u07c4\7K\2\2\u07c4\u07c5"+ + "\7I\2\2\u07c5\u07c6\7J\2\2\u07c6\u07c7\7V\2\2\u07c7\u01a4\3\2\2\2\u07c8"+ + "\u07c9\7N\2\2\u07c9\u07ca\7G\2\2\u07ca\u07cb\7H\2\2\u07cb\u07cc\7V\2\2"+ + "\u07cc\u01a6\3\2\2\2\u07cd\u07ce\7C\2\2\u07ce\u07cf\7U\2\2\u07cf\u07d0"+ + "\7E\2\2\u07d0\u07d1\7K\2\2\u07d1\u07d2\7K\2\2\u07d2\u01a8\3\2\2\2\u07d3"+ + "\u07d4\7N\2\2\u07d4\u07d5\7Q\2\2\u07d5\u07d6\7E\2\2\u07d6\u07d7\7C\2\2"+ + "\u07d7\u07d8\7V\2\2\u07d8\u07d9\7G\2\2\u07d9\u01aa\3\2\2\2\u07da\u07db"+ + "\7T\2\2\u07db\u07dc\7G\2\2\u07dc\u07dd\7R\2\2\u07dd\u07de\7N\2\2\u07de"+ + "\u07df\7C\2\2\u07df\u07e0\7E\2\2\u07e0\u07e1\7G\2\2\u07e1\u01ac\3\2\2"+ + "\2\u07e2\u07e3\7E\2\2\u07e3\u07e4\7C\2\2\u07e4\u07e5\7U\2\2\u07e5\u07e6"+ + "\7V\2\2\u07e6\u01ae\3\2\2\2\u07e7\u07e8\7N\2\2\u07e8\u07e9\7K\2\2\u07e9"+ + "\u07ea\7M\2\2\u07ea\u07eb\7G\2\2\u07eb\u01b0\3\2\2\2\u07ec\u07ed\7K\2"+ + "\2\u07ed\u07ee\7U\2\2\u07ee\u07ef\7P\2\2\u07ef\u07f0\7W\2\2\u07f0\u07f1"+ + "\7N\2\2\u07f1\u07f2\7N\2\2\u07f2\u01b2\3\2\2\2\u07f3\u07f4\7K\2\2\u07f4"+ + "\u07f5\7U\2\2\u07f5\u07f6\7P\2\2\u07f6\u07f7\7Q\2\2\u07f7\u07f8\7V\2\2"+ + "\u07f8\u07f9\7P\2\2\u07f9\u07fa\7W\2\2\u07fa\u07fb\7N\2\2\u07fb\u07fc"+ + "\7N\2\2\u07fc\u01b4\3\2\2\2\u07fd\u07fe\7K\2\2\u07fe\u07ff\7H\2\2\u07ff"+ + "\u0800\7P\2\2\u0800\u0801\7W\2\2\u0801\u0802\7N\2\2\u0802\u0803\7N\2\2"+ + "\u0803\u01b6\3\2\2\2\u0804\u0805\7P\2\2\u0805\u0806\7W\2\2\u0806\u0807"+ + "\7N\2\2\u0807\u0808\7N\2\2\u0808\u0809\7K\2\2\u0809\u080a\7H\2\2\u080a"+ + "\u01b8\3\2\2\2\u080b\u080c\7K\2\2\u080c\u080d\7H\2\2\u080d\u01ba\3\2\2"+ + "\2\u080e\u080f\7O\2\2\u080f\u0810\7C\2\2\u0810\u0811\7V\2\2\u0811\u0812"+ + "\7E\2\2\u0812\u0813\7J\2\2\u0813\u01bc\3\2\2\2\u0814\u0815\7O\2\2\u0815"+ + "\u0816\7C\2\2\u0816\u0817\7V\2\2\u0817\u0818\7E\2\2\u0818\u0819\7J\2\2"+ + "\u0819\u081a\7a\2\2\u081a\u081b\7R\2\2\u081b\u081c\7J\2\2\u081c\u081d"+ + "\7T\2\2\u081d\u081e\7C\2\2\u081e\u081f\7U\2\2\u081f\u0820\7G\2\2\u0820"+ + "\u01be\3\2\2\2\u0821\u0822\7U\2\2\u0822\u0823\7K\2\2\u0823\u0824\7O\2"+ + "\2\u0824\u0825\7R\2\2\u0825\u0826\7N\2\2\u0826\u0827\7G\2\2\u0827\u0828"+ + "\7a\2\2\u0828\u0829\7S\2\2\u0829\u082a\7W\2\2\u082a\u082b\7G\2\2\u082b"+ + "\u082c\7T\2\2\u082c\u082d\7[\2\2\u082d\u082e\7a\2\2\u082e\u082f\7U\2\2"+ + "\u082f\u0830\7V\2\2\u0830\u0831\7T\2\2\u0831\u0832\7K\2\2\u0832\u0833"+ + "\7P\2\2\u0833\u0834\7I\2\2\u0834\u01c0\3\2\2\2\u0835\u0836\7C\2\2\u0836"+ + "\u0837\7N\2\2\u0837\u0838\7N\2\2\u0838\u0839\7Q\2\2\u0839\u083a\7Y\2\2"+ + "\u083a\u083b\7a\2\2\u083b\u083c\7N\2\2\u083c\u083d\7G\2\2\u083d\u083e"+ + "\7C\2\2\u083e\u083f\7F\2\2\u083f\u0840\7K\2\2\u0840\u0841\7P\2\2\u0841"+ + "\u0842\7I\2\2\u0842\u0843\7a\2\2\u0843\u0844\7Y\2\2\u0844\u0845\7K\2\2"+ + "\u0845\u0846\7N\2\2\u0846\u0847\7F\2\2\u0847\u0848\7E\2\2\u0848\u0849"+ + "\7C\2\2\u0849\u084a\7T\2\2\u084a\u084b\7F\2\2\u084b\u01c2\3\2\2\2\u084c"+ + "\u084d\7C\2\2\u084d\u084e\7P\2\2\u084e\u084f\7C\2\2\u084f\u0850\7N\2\2"+ + "\u0850\u0851\7[\2\2\u0851\u0852\7\\\2\2\u0852\u0853\7G\2\2\u0853\u0854"+ + "\7a\2\2\u0854\u0855\7Y\2\2\u0855\u0856\7K\2\2\u0856\u0857\7N\2\2\u0857"+ + "\u0858\7F\2\2\u0858\u0859\7E\2\2\u0859\u085a\7C\2\2\u085a\u085b\7T\2\2"+ + "\u085b\u085c\7F\2\2\u085c\u01c4\3\2\2\2\u085d\u085e\7C\2\2\u085e\u085f"+ + "\7P\2\2\u085f\u0860\7C\2\2\u0860\u0861\7N\2\2\u0861\u0862\7[\2\2\u0862"+ + "\u0863\7\\\2\2\u0863\u0864\7G\2\2\u0864\u0865\7T\2\2\u0865\u01c6\3\2\2"+ + "\2\u0866\u0867\7C\2\2\u0867\u0868\7W\2\2\u0868\u0869\7V\2\2\u0869\u086a"+ + "\7Q\2\2\u086a\u086b\7a\2\2\u086b\u086c\7I\2\2\u086c\u086d\7G\2\2\u086d"+ + "\u086e\7P\2\2\u086e\u086f\7G\2\2\u086f\u0870\7T\2\2\u0870\u0871\7C\2\2"+ + "\u0871\u0872\7V\2\2\u0872\u0873\7G\2\2\u0873\u0874\7a\2\2\u0874\u0875"+ + "\7U\2\2\u0875\u0876\7[\2\2\u0876\u0877\7P\2\2\u0877\u0878\7Q\2\2\u0878"+ + "\u0879\7P\2\2\u0879\u087a\7[\2\2\u087a\u087b\7O\2\2\u087b\u087c\7U\2\2"+ + "\u087c\u087d\7a\2\2\u087d\u087e\7R\2\2\u087e\u087f\7J\2\2\u087f\u0880"+ + "\7T\2\2\u0880\u0881\7C\2\2\u0881\u0882\7U\2\2\u0882\u0883\7G\2\2\u0883"+ + "\u0884\7a\2\2\u0884\u0885\7S\2\2\u0885\u0886\7W\2\2\u0886\u0887\7G\2\2"+ + "\u0887\u0888\7T\2\2\u0888\u0889\7[\2\2\u0889\u01c8\3\2\2\2\u088a\u088b"+ + "\7D\2\2\u088b\u088c\7Q\2\2\u088c\u088d\7Q\2\2\u088d\u088e\7U\2\2\u088e"+ + "\u088f\7V\2\2\u088f\u01ca\3\2\2\2\u0890\u0891\7E\2\2\u0891\u0892\7W\2"+ + "\2\u0892\u0893\7V\2\2\u0893\u0894\7Q\2\2\u0894\u0895\7H\2\2\u0895\u0896"+ + "\7H\2\2\u0896\u0897\7a\2\2\u0897\u0898\7H\2\2\u0898\u0899\7T\2\2\u0899"+ + "\u089a\7G\2\2\u089a\u089b\7S\2\2\u089b\u089c\7W\2\2\u089c\u089d\7G\2\2"+ + "\u089d\u089e\7P\2\2\u089e\u089f\7E\2\2\u089f\u08a0\7[\2\2\u08a0\u01cc"+ + "\3\2\2\2\u08a1\u08a2\7F\2\2\u08a2\u08a3\7G\2\2\u08a3\u08a4\7H\2\2\u08a4"+ + "\u08a5\7C\2\2\u08a5\u08a6\7W\2\2\u08a6\u08a7\7N\2\2\u08a7\u08a8\7V\2\2"+ + "\u08a8\u08a9\7a\2\2\u08a9\u08aa\7H\2\2\u08aa\u08ab\7K\2\2\u08ab\u08ac"+ + "\7G\2\2\u08ac\u08ad\7N\2\2\u08ad\u08ae\7F\2\2\u08ae\u01ce\3\2\2\2\u08af"+ + "\u08b0\7F\2\2\u08b0\u08b1\7G\2\2\u08b1\u08b2\7H\2\2\u08b2\u08b3\7C\2\2"+ + "\u08b3\u08b4\7W\2\2\u08b4\u08b5\7N\2\2\u08b5\u08b6\7V\2\2\u08b6\u08b7"+ + "\7a\2\2\u08b7\u08b8\7Q\2\2\u08b8\u08b9\7R\2\2\u08b9\u08ba\7G\2\2\u08ba"+ + "\u08bb\7T\2\2\u08bb\u08bc\7C\2\2\u08bc\u08bd\7V\2\2\u08bd\u08be\7Q\2\2"+ + "\u08be\u08bf\7T\2\2\u08bf\u01d0\3\2\2\2\u08c0\u08c1\7G\2\2\u08c1\u08c2"+ + "\7P\2\2\u08c2\u08c3\7C\2\2\u08c3\u08c4\7D\2\2\u08c4\u08c5\7N\2\2\u08c5"+ + "\u08c6\7G\2\2\u08c6\u08c7\7a\2\2\u08c7\u08c8\7R\2\2\u08c8\u08c9\7Q\2\2"+ + "\u08c9\u08ca\7U\2\2\u08ca\u08cb\7K\2\2\u08cb\u08cc\7V\2\2\u08cc\u08cd"+ + "\7K\2\2\u08cd\u08ce\7Q\2\2\u08ce\u08cf\7P\2\2\u08cf\u08d0\7a\2\2\u08d0"+ + "\u08d1\7K\2\2\u08d1\u08d2\7P\2\2\u08d2\u08d3\7E\2\2\u08d3\u08d4\7T\2\2"+ + "\u08d4\u08d5\7G\2\2\u08d5\u08d6\7O\2\2\u08d6\u08d7\7G\2\2\u08d7\u08d8"+ + "\7P\2\2\u08d8\u08d9\7V\2\2\u08d9\u08da\7U\2\2\u08da\u01d2\3\2\2\2\u08db"+ + "\u08dc\7H\2\2\u08dc\u08dd\7N\2\2\u08dd\u08de\7C\2\2\u08de\u08df\7I\2\2"+ + "\u08df\u08e0\7U\2\2\u08e0\u01d4\3\2\2\2\u08e1\u08e2\7H\2\2\u08e2\u08e3"+ + "\7W\2\2\u08e3\u08e4\7\\\2\2\u08e4\u08e5\7\\\2\2\u08e5\u08e6\7[\2\2\u08e6"+ + "\u08e7\7a\2\2\u08e7\u08e8\7O\2\2\u08e8\u08e9\7C\2\2\u08e9\u08ea\7Z\2\2"+ + "\u08ea\u08eb\7a\2\2\u08eb\u08ec\7G\2\2\u08ec\u08ed\7Z\2\2\u08ed\u08ee"+ + "\7R\2\2\u08ee\u08ef\7C\2\2\u08ef\u08f0\7P\2\2\u08f0\u08f1\7U\2\2\u08f1"+ + "\u08f2\7K\2\2\u08f2\u08f3\7Q\2\2\u08f3\u08f4\7P\2\2\u08f4\u08f5\7U\2\2"+ + "\u08f5\u01d6\3\2\2\2\u08f6\u08f7\7H\2\2\u08f7\u08f8\7W\2\2\u08f8\u08f9"+ + "\7\\\2\2\u08f9\u08fa\7\\\2\2\u08fa\u08fb\7[\2\2\u08fb\u08fc\7a\2\2\u08fc"+ + "\u08fd\7R\2\2\u08fd\u08fe\7T\2\2\u08fe\u08ff\7G\2\2\u08ff\u0900\7H\2\2"+ + "\u0900\u0901\7K\2\2\u0901\u0902\7Z\2\2\u0902\u0903\7a\2\2\u0903\u0904"+ + "\7N\2\2\u0904\u0905\7G\2\2\u0905\u0906\7P\2\2\u0906\u0907\7I\2\2\u0907"+ + "\u0908\7V\2\2\u0908\u0909\7J\2\2\u0909\u01d8\3\2\2\2\u090a\u090b\7H\2"+ + "\2\u090b\u090c\7W\2\2\u090c\u090d\7\\\2\2\u090d\u090e\7\\\2\2\u090e\u090f"+ + "\7[\2\2\u090f\u0910\7a\2\2\u0910\u0911\7V\2\2\u0911\u0912\7T\2\2\u0912"+ + "\u0913\7C\2\2\u0913\u0914\7P\2\2\u0914\u0915\7U\2\2\u0915\u0916\7R\2\2"+ + "\u0916\u0917\7Q\2\2\u0917\u0918\7U\2\2\u0918\u0919\7K\2\2\u0919\u091a"+ + "\7V\2\2\u091a\u091b\7K\2\2\u091b\u091c\7Q\2\2\u091c\u091d\7P\2\2\u091d"+ + "\u091e\7U\2\2\u091e\u01da\3\2\2\2\u091f\u0920\7H\2\2\u0920\u0921\7W\2"+ + "\2\u0921\u0922\7\\\2\2\u0922\u0923\7\\\2\2\u0923\u0924\7[\2\2\u0924\u0925"+ + "\7a\2\2\u0925\u0926\7T\2\2\u0926\u0927\7G\2\2\u0927\u0928\7Y\2\2\u0928"+ + "\u0929\7T\2\2\u0929\u092a\7K\2\2\u092a\u092b\7V\2\2\u092b\u092c\7G\2\2"+ + "\u092c\u01dc\3\2\2\2\u092d\u092e\7H\2\2\u092e\u092f\7W\2\2\u092f\u0930"+ + "\7\\\2\2\u0930\u0931\7\\\2\2\u0931\u0932\7K\2\2\u0932\u0933\7P\2\2\u0933"+ + "\u0934\7G\2\2\u0934\u0935\7U\2\2\u0935\u0936\7U\2\2\u0936\u01de\3\2\2"+ + "\2\u0937\u0938\7N\2\2\u0938\u0939\7G\2\2\u0939\u093a\7P\2\2\u093a\u093b"+ + "\7K\2\2\u093b\u093c\7G\2\2\u093c\u093d\7P\2\2\u093d\u093e\7V\2\2\u093e"+ + "\u01e0\3\2\2\2\u093f\u0940\7N\2\2\u0940\u0941\7Q\2\2\u0941\u0942\7Y\2"+ + "\2\u0942\u0943\7a\2\2\u0943\u0944\7H\2\2\u0944\u0945\7T\2\2\u0945\u0946"+ + "\7G\2\2\u0946\u0947\7S\2\2\u0947\u0948\7a\2\2\u0948\u0949\7Q\2\2\u0949"+ + "\u094a\7R\2\2\u094a\u094b\7G\2\2\u094b\u094c\7T\2\2\u094c\u094d\7C\2\2"+ + "\u094d\u094e\7V\2\2\u094e\u094f\7Q\2\2\u094f\u0950\7T\2\2\u0950\u01e2"+ + "\3\2\2\2\u0951\u0952\7O\2\2\u0952\u0953\7C\2\2\u0953\u0954\7Z\2\2\u0954"+ + "\u0955\7a\2\2\u0955\u0956\7F\2\2\u0956\u0957\7G\2\2\u0957\u0958\7V\2\2"+ + "\u0958\u0959\7G\2\2\u0959\u095a\7T\2\2\u095a\u095b\7O\2\2\u095b\u095c"+ + "\7K\2\2\u095c\u095d\7P\2\2\u095d\u095e\7K\2\2\u095e\u095f\7\\\2\2\u095f"+ + "\u0960\7G\2\2\u0960\u0961\7F\2\2\u0961\u0962\7a\2\2\u0962\u0963\7U\2\2"+ + "\u0963\u0964\7V\2\2\u0964\u0965\7C\2\2\u0965\u0966\7V\2\2\u0966\u0967"+ + "\7G\2\2\u0967\u0968\7U\2\2\u0968\u01e4\3\2\2\2\u0969\u096a\7O\2\2\u096a"+ + "\u096b\7C\2\2\u096b\u096c\7Z\2\2\u096c\u096d\7a\2\2\u096d\u096e\7G\2\2"+ + "\u096e\u096f\7Z\2\2\u096f\u0970\7R\2\2\u0970\u0971\7C\2\2\u0971\u0972"+ + "\7P\2\2\u0972\u0973\7U\2\2\u0973\u0974\7K\2\2\u0974\u0975\7Q\2\2\u0975"+ + "\u0976\7P\2\2\u0976\u0977\7U\2\2\u0977\u01e6\3\2\2\2\u0978\u0979\7O\2"+ + "\2\u0979\u097a\7K\2\2\u097a\u097b\7P\2\2\u097b\u097c\7K\2\2\u097c\u097d"+ + "\7O\2\2\u097d\u097e\7W\2\2\u097e\u097f\7O\2\2\u097f\u0980\7a\2\2\u0980"+ + "\u0981\7U\2\2\u0981\u0982\7J\2\2\u0982\u0983\7Q\2\2\u0983\u0984\7W\2\2"+ + "\u0984\u0985\7N\2\2\u0985\u0986\7F\2\2\u0986\u0987\7a\2\2\u0987\u0988"+ + "\7O\2\2\u0988\u0989\7C\2\2\u0989\u098a\7V\2\2\u098a\u098b\7E\2\2\u098b"+ + "\u098c\7J\2\2\u098c\u01e8\3\2\2\2\u098d\u098e\7Q\2\2\u098e\u098f\7R\2"+ + "\2\u098f\u0990\7G\2\2\u0990\u0991\7T\2\2\u0991\u0992\7C\2\2\u0992\u0993"+ + "\7V\2\2\u0993\u0994\7Q\2\2\u0994\u0995\7T\2\2\u0995\u01ea\3\2\2\2\u0996"+ + "\u0997\7R\2\2\u0997\u0998\7J\2\2\u0998\u0999\7T\2\2\u0999\u099a\7C\2\2"+ + "\u099a\u099b\7U\2\2\u099b\u099c\7G\2\2\u099c\u099d\7a\2\2\u099d\u099e"+ + "\7U\2\2\u099e\u099f\7N\2\2\u099f\u09a0\7Q\2\2\u09a0\u09a1\7R\2\2\u09a1"+ + "\u01ec\3\2\2\2\u09a2\u09a3\7R\2\2\u09a3\u09a4\7T\2\2\u09a4\u09a5\7G\2"+ + "\2\u09a5\u09a6\7H\2\2\u09a6\u09a7\7K\2\2\u09a7\u09a8\7Z\2\2\u09a8\u09a9"+ + "\7a\2\2\u09a9\u09aa\7N\2\2\u09aa\u09ab\7G\2\2\u09ab\u09ac\7P\2\2\u09ac"+ + "\u09ad\7I\2\2\u09ad\u09ae\7V\2\2\u09ae\u09af\7J\2\2\u09af\u01ee\3\2\2"+ + "\2\u09b0\u09b1\7S\2\2\u09b1\u09b2\7W\2\2\u09b2\u09b3\7Q\2\2\u09b3\u09b4"+ + "\7V\2\2\u09b4\u09b5\7G\2\2\u09b5\u09b6\7a\2\2\u09b6\u09b7\7C\2\2\u09b7"+ + "\u09b8\7P\2\2\u09b8\u09b9\7C\2\2\u09b9\u09ba\7N\2\2\u09ba\u09bb\7[\2\2"+ + "\u09bb\u09bc\7\\\2\2\u09bc\u09bd\7G\2\2\u09bd\u09be\7T\2\2\u09be\u01f0"+ + "\3\2\2\2\u09bf\u09c0\7S\2\2\u09c0\u09c1\7W\2\2\u09c1\u09c2\7Q\2\2\u09c2"+ + "\u09c3\7V\2\2\u09c3\u09c4\7G\2\2\u09c4\u09c5\7a\2\2\u09c5\u09c6\7H\2\2"+ + "\u09c6\u09c7\7K\2\2\u09c7\u09c8\7G\2\2\u09c8\u09c9\7N\2\2\u09c9\u09ca"+ + "\7F\2\2\u09ca\u09cb\7a\2\2\u09cb\u09cc\7U\2\2\u09cc\u09cd\7W\2\2\u09cd"+ + "\u09ce\7H\2\2\u09ce\u09cf\7H\2\2\u09cf\u09d0\7K\2\2\u09d0\u09d1\7Z\2\2"+ + "\u09d1\u01f2\3\2\2\2\u09d2\u09d3\7T\2\2\u09d3\u09d4\7G\2\2\u09d4\u09d5"+ + "\7Y\2\2\u09d5\u09d6\7T\2\2\u09d6\u09d7\7K\2\2\u09d7\u09d8\7V\2\2\u09d8"+ + "\u09d9\7G\2\2\u09d9\u01f4\3\2\2\2\u09da\u09db\7U\2\2\u09db\u09dc\7N\2"+ + "\2\u09dc\u09dd\7Q\2\2\u09dd\u09de\7R\2\2\u09de\u01f6\3\2\2\2\u09df\u09e0"+ + "\7V\2\2\u09e0\u09e1\7K\2\2\u09e1\u09e2\7G\2\2\u09e2\u09e3\7a\2\2\u09e3"+ + "\u09e4\7D\2\2\u09e4\u09e5\7T\2\2\u09e5\u09e6\7G\2\2\u09e6\u09e7\7C\2\2"+ + "\u09e7\u09e8\7M\2\2\u09e8\u09e9\7G\2\2\u09e9\u09ea\7T\2\2\u09ea\u01f8"+ + "\3\2\2\2\u09eb\u09ec\7V\2\2\u09ec\u09ed\7[\2\2\u09ed\u09ee\7R\2\2\u09ee"+ + "\u09ef\7G\2\2\u09ef\u01fa\3\2\2\2\u09f0\u09f1\7\\\2\2\u09f1\u09f2\7G\2"+ + "\2\u09f2\u09f3\7T\2\2\u09f3\u09f4\7Q\2\2\u09f4\u09f5\7a\2\2\u09f5\u09f6"+ + "\7V\2\2\u09f6\u09f7\7G\2\2\u09f7\u09f8\7T\2\2\u09f8\u09f9\7O\2\2\u09f9"+ + "\u09fa\7U\2\2\u09fa\u09fb\7a\2\2\u09fb\u09fc\7S\2\2\u09fc\u09fd\7W\2\2"+ + "\u09fd\u09fe\7G\2\2\u09fe\u09ff\7T\2\2\u09ff\u0a00\7[\2\2\u0a00\u01fc"+ + "\3\2\2\2\u0a01\u0a02\7U\2\2\u0a02\u0a03\7R\2\2\u0a03\u0a04\7C\2\2\u0a04"+ + "\u0a05\7P\2\2\u0a05\u01fe\3\2\2\2\u0a06\u0a07\7O\2\2\u0a07\u0a08\7U\2"+ + "\2\u0a08\u0200\3\2\2\2\u0a09\u0a0a\7U\2\2\u0a0a\u0202\3\2\2\2\u0a0b\u0a0c"+ + "\7O\2\2\u0a0c\u0204\3\2\2\2\u0a0d\u0a0e\7J\2\2\u0a0e\u0206\3\2\2\2\u0a0f"+ + "\u0a10\7Y\2\2\u0a10\u0208\3\2\2\2\u0a11\u0a12\7S\2\2\u0a12\u020a\3\2\2"+ + "\2\u0a13\u0a14\7[\2\2\u0a14\u020c\3\2\2\2\u0a15\u0a16\5\u0215\u010b\2"+ + "\u0a16\u020e\3\2\2\2\u0a17\u0a19\5\u021f\u0110\2\u0a18\u0a17\3\2\2\2\u0a19"+ + "\u0a1a\3\2\2\2\u0a1a\u0a18\3\2\2\2\u0a1a\u0a1b\3\2\2\2\u0a1b\u0210\3\2"+ + "\2\2\u0a1c\u0a1e\5\u021f\u0110\2\u0a1d\u0a1c\3\2\2\2\u0a1e\u0a1f\3\2\2"+ + "\2\u0a1f\u0a1d\3\2\2\2\u0a1f\u0a20\3\2\2\2\u0a20\u0a22\3\2\2\2\u0a21\u0a1d"+ + "\3\2\2\2\u0a21\u0a22\3\2\2\2\u0a22\u0a23\3\2\2\2\u0a23\u0a25\7\60\2\2"+ + "\u0a24\u0a26\5\u021f\u0110\2\u0a25\u0a24\3\2\2\2\u0a26\u0a27\3\2\2\2\u0a27"+ + "\u0a25\3\2\2\2\u0a27\u0a28\3\2\2\2\u0a28\u0212\3\2\2\2\u0a29\u0a2b\t\2"+ + "\2\2\u0a2a\u0a2c\t\3\2\2\u0a2b\u0a2a\3\2\2\2\u0a2c\u0a2d\3\2\2\2\u0a2d"+ + "\u0a2b\3\2\2\2\u0a2d\u0a2e\3\2\2\2\u0a2e\u0a30\3\2\2\2\u0a2f\u0a29\3\2"+ + "\2\2\u0a30\u0a33\3\2\2\2\u0a31\u0a2f\3\2\2\2\u0a31\u0a32\3\2\2\2\u0a32"+ + "\u0214\3\2\2\2\u0a33\u0a31\3\2\2\2\u0a34\u0a36\t\4\2\2\u0a35\u0a34\3\2"+ + "\2\2\u0a36\u0a37\3\2\2\2\u0a37\u0a38\3\2\2\2\u0a37\u0a35\3\2\2\2\u0a38"+ + "\u0a3c\3\2\2\2\u0a39\u0a3b\t\5\2\2\u0a3a\u0a39\3\2\2\2\u0a3b\u0a3e\3\2"+ + "\2\2\u0a3c\u0a3a\3\2\2\2\u0a3c\u0a3d\3\2\2\2\u0a3d\u0216\3\2\2\2\u0a3e"+ + "\u0a3c\3\2\2\2\u0a3f\u0a40\5\u0215\u010b\2\u0a40\u0a41\5\u0213\u010a\2"+ + "\u0a41\u0218\3\2\2\2\u0a42\u0a4a\7$\2\2\u0a43\u0a44\7^\2\2\u0a44\u0a49"+ + "\13\2\2\2\u0a45\u0a46\7$\2\2\u0a46\u0a49\7$\2\2\u0a47\u0a49\n\6\2\2\u0a48"+ + "\u0a43\3\2\2\2\u0a48\u0a45\3\2\2\2\u0a48\u0a47\3\2\2\2\u0a49\u0a4c\3\2"+ + "\2\2\u0a4a\u0a48\3\2\2\2\u0a4a\u0a4b\3\2\2\2\u0a4b\u0a4d\3\2\2\2\u0a4c"+ + "\u0a4a\3\2\2\2\u0a4d\u0a4e\7$\2\2\u0a4e\u021a\3\2\2\2\u0a4f\u0a57\7)\2"+ + "\2\u0a50"; + private static final String _serializedATNSegment1 = + "\u0a51\7^\2\2\u0a51\u0a56\13\2\2\2\u0a52\u0a53\7)\2\2\u0a53\u0a56\7)\2"+ + "\2\u0a54\u0a56\n\7\2\2\u0a55\u0a50\3\2\2\2\u0a55\u0a52\3\2\2\2\u0a55\u0a54"+ + "\3\2\2\2\u0a56\u0a59\3\2\2\2\u0a57\u0a55\3\2\2\2\u0a57\u0a58\3\2\2\2\u0a58"+ + "\u0a5a\3\2\2\2\u0a59\u0a57\3\2\2\2\u0a5a\u0a5b\7)\2\2\u0a5b\u021c\3\2"+ + "\2\2\u0a5c\u0a64\7b\2\2\u0a5d\u0a5e\7^\2\2\u0a5e\u0a63\13\2\2\2\u0a5f"+ + "\u0a60\7b\2\2\u0a60\u0a63\7b\2\2\u0a61\u0a63\n\b\2\2\u0a62\u0a5d\3\2\2"+ + "\2\u0a62\u0a5f\3\2\2\2\u0a62\u0a61\3\2\2\2\u0a63\u0a66\3\2\2\2\u0a64\u0a62"+ + "\3\2\2\2\u0a64\u0a65\3\2\2\2\u0a65\u0a67\3\2\2\2\u0a66\u0a64\3\2\2\2\u0a67"+ + "\u0a68\7b\2\2\u0a68\u021e\3\2\2\2\u0a69\u0a6a\t\t\2\2\u0a6a\u0220\3\2"+ + "\2\2\u0a6b\u0a6c\13\2\2\2\u0a6c\u0a6d\3\2\2\2\u0a6d\u0a6e\b\u0111\2\2"+ + "\u0a6e\u0222\3\2\2\2\21\2\u0a1a\u0a1f\u0a21\u0a27\u0a2d\u0a31\u0a37\u0a3c"+ + "\u0a48\u0a4a\u0a55\u0a57\u0a62\u0a64\3\2\5\2"; + public static final String _serializedATN = Utils.join( + new String[] { + _serializedATNSegment0, + _serializedATNSegment1 + }, + "" + ); + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/dashboards-observability/common/query_manager/antlr/grammar/.antlr/OpenSearchPPLLexer.tokens b/dashboards-observability/common/query_manager/antlr/grammar/.antlr/OpenSearchPPLLexer.tokens new file mode 100644 index 000000000..e7b58d1ef --- /dev/null +++ b/dashboards-observability/common/query_manager/antlr/grammar/.antlr/OpenSearchPPLLexer.tokens @@ -0,0 +1,527 @@ +SEARCH=1 +FROM=2 +WHERE=3 +FIELDS=4 +RENAME=5 +STATS=6 +DEDUP=7 +SORT=8 +EVAL=9 +HEAD=10 +TOP=11 +RARE=12 +PARSE=13 +KMEANS=14 +AD=15 +AS=16 +BY=17 +SOURCE=18 +INDEX=19 +D=20 +DESC=21 +SORTBY=22 +AUTO=23 +STR=24 +IP=25 +NUM=26 +KEEPEMPTY=27 +CONSECUTIVE=28 +DEDUP_SPLITVALUES=29 +PARTITIONS=30 +ALLNUM=31 +DELIM=32 +CENTROIDS=33 +ITERATIONS=34 +DISTANCE_TYPE=35 +NUMBER_OF_TREES=36 +SHINGLE_SIZE=37 +SAMPLE_SIZE=38 +OUTPUT_AFTER=39 +TIME_DECAY=40 +ANOMALY_RATE=41 +TIME_FIELD=42 +TIME_ZONE=43 +TRAINING_DATA_SIZE=44 +ANOMALY_SCORE_THRESHOLD=45 +CASE=46 +IN=47 +NOT=48 +OR=49 +AND=50 +XOR=51 +TRUE=52 +FALSE=53 +REGEXP=54 +DATETIME=55 +INTERVAL=56 +MICROSECOND=57 +MILLISECOND=58 +SECOND=59 +MINUTE=60 +HOUR=61 +DAY=62 +WEEK=63 +MONTH=64 +QUARTER=65 +YEAR=66 +SECOND_MICROSECOND=67 +MINUTE_MICROSECOND=68 +MINUTE_SECOND=69 +HOUR_MICROSECOND=70 +HOUR_SECOND=71 +HOUR_MINUTE=72 +DAY_MICROSECOND=73 +DAY_SECOND=74 +DAY_MINUTE=75 +DAY_HOUR=76 +YEAR_MONTH=77 +DATAMODEL=78 +LOOKUP=79 +SAVEDSEARCH=80 +INT=81 +INTEGER=82 +DOUBLE=83 +LONG=84 +FLOAT=85 +STRING=86 +BOOLEAN=87 +PIPE=88 +COMMA=89 +DOT=90 +EQUAL=91 +GREATER=92 +LESS=93 +NOT_GREATER=94 +NOT_LESS=95 +NOT_EQUAL=96 +PLUS=97 +MINUS=98 +STAR=99 +DIVIDE=100 +MODULE=101 +EXCLAMATION_SYMBOL=102 +COLON=103 +LT_PRTHS=104 +RT_PRTHS=105 +LT_SQR_PRTHS=106 +RT_SQR_PRTHS=107 +SINGLE_QUOTE=108 +DOUBLE_QUOTE=109 +BACKTICK=110 +BIT_NOT_OP=111 +BIT_AND_OP=112 +BIT_XOR_OP=113 +AVG=114 +COUNT=115 +DISTINCT_COUNT=116 +ESTDC=117 +ESTDC_ERROR=118 +MAX=119 +MEAN=120 +MEDIAN=121 +MIN=122 +MODE=123 +RANGE=124 +STDEV=125 +STDEVP=126 +SUM=127 +SUMSQ=128 +VAR_SAMP=129 +VAR_POP=130 +STDDEV_SAMP=131 +STDDEV_POP=132 +PERCENTILE=133 +FIRST=134 +LAST=135 +LIST=136 +VALUES=137 +EARLIEST=138 +EARLIEST_TIME=139 +LATEST=140 +LATEST_TIME=141 +PER_DAY=142 +PER_HOUR=143 +PER_MINUTE=144 +PER_SECOND=145 +RATE=146 +SPARKLINE=147 +C=148 +DC=149 +ABS=150 +CEIL=151 +CEILING=152 +CONV=153 +CRC32=154 +E=155 +EXP=156 +FLOOR=157 +LN=158 +LOG=159 +LOG10=160 +LOG2=161 +MOD=162 +PI=163 +POW=164 +POWER=165 +RAND=166 +ROUND=167 +SIGN=168 +SQRT=169 +TRUNCATE=170 +ACOS=171 +ASIN=172 +ATAN=173 +ATAN2=174 +COS=175 +COT=176 +DEGREES=177 +RADIANS=178 +SIN=179 +TAN=180 +ADDDATE=181 +DATE=182 +DATE_ADD=183 +DATE_SUB=184 +DAYOFMONTH=185 +DAYOFWEEK=186 +DAYOFYEAR=187 +DAYNAME=188 +FROM_DAYS=189 +MONTHNAME=190 +SUBDATE=191 +TIME=192 +TIME_TO_SEC=193 +TIMESTAMP=194 +DATE_FORMAT=195 +TO_DAYS=196 +SUBSTR=197 +SUBSTRING=198 +LTRIM=199 +RTRIM=200 +TRIM=201 +TO=202 +LOWER=203 +UPPER=204 +CONCAT=205 +CONCAT_WS=206 +LENGTH=207 +STRCMP=208 +RIGHT=209 +LEFT=210 +ASCII=211 +LOCATE=212 +REPLACE=213 +CAST=214 +LIKE=215 +ISNULL=216 +ISNOTNULL=217 +IFNULL=218 +NULLIF=219 +IF=220 +MATCH=221 +MATCH_PHRASE=222 +SIMPLE_QUERY_STRING=223 +ALLOW_LEADING_WILDCARD=224 +ANALYZE_WILDCARD=225 +ANALYZER=226 +AUTO_GENERATE_SYNONYMS_PHRASE_QUERY=227 +BOOST=228 +CUTOFF_FREQUENCY=229 +DEFAULT_FIELD=230 +DEFAULT_OPERATOR=231 +ENABLE_POSITION_INCREMENTS=232 +FLAGS=233 +FUZZY_MAX_EXPANSIONS=234 +FUZZY_PREFIX_LENGTH=235 +FUZZY_TRANSPOSITIONS=236 +FUZZY_REWRITE=237 +FUZZINESS=238 +LENIENT=239 +LOW_FREQ_OPERATOR=240 +MAX_DETERMINIZED_STATES=241 +MAX_EXPANSIONS=242 +MINIMUM_SHOULD_MATCH=243 +OPERATOR=244 +PHRASE_SLOP=245 +PREFIX_LENGTH=246 +QUOTE_ANALYZER=247 +QUOTE_FIELD_SUFFIX=248 +REWRITE=249 +SLOP=250 +TIE_BREAKER=251 +TYPE=252 +ZERO_TERMS_QUERY=253 +SPAN=254 +MS=255 +S=256 +M=257 +H=258 +W=259 +Q=260 +Y=261 +ID=262 +INTEGER_LITERAL=263 +DECIMAL_LITERAL=264 +ID_DATE_SUFFIX=265 +DQUOTA_STRING=266 +SQUOTA_STRING=267 +BQUOTA_STRING=268 +ERROR_RECOGNITION=269 +'SEARCH'=1 +'FROM'=2 +'WHERE'=3 +'FIELDS'=4 +'RENAME'=5 +'STATS'=6 +'DEDUP'=7 +'SORT'=8 +'EVAL'=9 +'HEAD'=10 +'TOP'=11 +'RARE'=12 +'PARSE'=13 +'KMEANS'=14 +'AD'=15 +'AS'=16 +'BY'=17 +'SOURCE'=18 +'INDEX'=19 +'D'=20 +'DESC'=21 +'SORTBY'=22 +'AUTO'=23 +'STR'=24 +'IP'=25 +'NUM'=26 +'KEEPEMPTY'=27 +'CONSECUTIVE'=28 +'DEDUP_SPLITVALUES'=29 +'PARTITIONS'=30 +'ALLNUM'=31 +'DELIM'=32 +'CENTROIDS'=33 +'ITERATIONS'=34 +'DISTANCE_TYPE'=35 +'NUMBER_OF_TREES'=36 +'SHINGLE_SIZE'=37 +'SAMPLE_SIZE'=38 +'OUTPUT_AFTER'=39 +'TIME_DECAY'=40 +'ANOMALY_RATE'=41 +'TIME_FIELD'=42 +'TIME_ZONE'=43 +'TRAINING_DATA_SIZE'=44 +'ANOMALY_SCORE_THRESHOLD'=45 +'CASE'=46 +'IN'=47 +'NOT'=48 +'OR'=49 +'AND'=50 +'XOR'=51 +'TRUE'=52 +'FALSE'=53 +'REGEXP'=54 +'DATETIME'=55 +'INTERVAL'=56 +'MICROSECOND'=57 +'MILLISECOND'=58 +'SECOND'=59 +'MINUTE'=60 +'HOUR'=61 +'DAY'=62 +'WEEK'=63 +'MONTH'=64 +'QUARTER'=65 +'YEAR'=66 +'SECOND_MICROSECOND'=67 +'MINUTE_MICROSECOND'=68 +'MINUTE_SECOND'=69 +'HOUR_MICROSECOND'=70 +'HOUR_SECOND'=71 +'HOUR_MINUTE'=72 +'DAY_MICROSECOND'=73 +'DAY_SECOND'=74 +'DAY_MINUTE'=75 +'DAY_HOUR'=76 +'YEAR_MONTH'=77 +'DATAMODEL'=78 +'LOOKUP'=79 +'SAVEDSEARCH'=80 +'INT'=81 +'INTEGER'=82 +'DOUBLE'=83 +'LONG'=84 +'FLOAT'=85 +'STRING'=86 +'BOOLEAN'=87 +'|'=88 +','=89 +'.'=90 +'='=91 +'>'=92 +'<'=93 +'+'=97 +'-'=98 +'*'=99 +'/'=100 +'%'=101 +'!'=102 +':'=103 +'('=104 +')'=105 +'['=106 +']'=107 +'\''=108 +'"'=109 +'`'=110 +'~'=111 +'&'=112 +'^'=113 +'AVG'=114 +'COUNT'=115 +'DISTINCT_COUNT'=116 +'ESTDC'=117 +'ESTDC_ERROR'=118 +'MAX'=119 +'MEAN'=120 +'MEDIAN'=121 +'MIN'=122 +'MODE'=123 +'RANGE'=124 +'STDEV'=125 +'STDEVP'=126 +'SUM'=127 +'SUMSQ'=128 +'VAR_SAMP'=129 +'VAR_POP'=130 +'STDDEV_SAMP'=131 +'STDDEV_POP'=132 +'PERCENTILE'=133 +'FIRST'=134 +'LAST'=135 +'LIST'=136 +'VALUES'=137 +'EARLIEST'=138 +'EARLIEST_TIME'=139 +'LATEST'=140 +'LATEST_TIME'=141 +'PER_DAY'=142 +'PER_HOUR'=143 +'PER_MINUTE'=144 +'PER_SECOND'=145 +'RATE'=146 +'SPARKLINE'=147 +'C'=148 +'DC'=149 +'ABS'=150 +'CEIL'=151 +'CEILING'=152 +'CONV'=153 +'CRC32'=154 +'E'=155 +'EXP'=156 +'FLOOR'=157 +'LN'=158 +'LOG'=159 +'LOG10'=160 +'LOG2'=161 +'MOD'=162 +'PI'=163 +'POW'=164 +'POWER'=165 +'RAND'=166 +'ROUND'=167 +'SIGN'=168 +'SQRT'=169 +'TRUNCATE'=170 +'ACOS'=171 +'ASIN'=172 +'ATAN'=173 +'ATAN2'=174 +'COS'=175 +'COT'=176 +'DEGREES'=177 +'RADIANS'=178 +'SIN'=179 +'TAN'=180 +'ADDDATE'=181 +'DATE'=182 +'DATE_ADD'=183 +'DATE_SUB'=184 +'DAYOFMONTH'=185 +'DAYOFWEEK'=186 +'DAYOFYEAR'=187 +'DAYNAME'=188 +'FROM_DAYS'=189 +'MONTHNAME'=190 +'SUBDATE'=191 +'TIME'=192 +'TIME_TO_SEC'=193 +'TIMESTAMP'=194 +'DATE_FORMAT'=195 +'TO_DAYS'=196 +'SUBSTR'=197 +'SUBSTRING'=198 +'LTRIM'=199 +'RTRIM'=200 +'TRIM'=201 +'TO'=202 +'LOWER'=203 +'UPPER'=204 +'CONCAT'=205 +'CONCAT_WS'=206 +'LENGTH'=207 +'STRCMP'=208 +'RIGHT'=209 +'LEFT'=210 +'ASCII'=211 +'LOCATE'=212 +'REPLACE'=213 +'CAST'=214 +'LIKE'=215 +'ISNULL'=216 +'ISNOTNULL'=217 +'IFNULL'=218 +'NULLIF'=219 +'IF'=220 +'MATCH'=221 +'MATCH_PHRASE'=222 +'SIMPLE_QUERY_STRING'=223 +'ALLOW_LEADING_WILDCARD'=224 +'ANALYZE_WILDCARD'=225 +'ANALYZER'=226 +'AUTO_GENERATE_SYNONYMS_PHRASE_QUERY'=227 +'BOOST'=228 +'CUTOFF_FREQUENCY'=229 +'DEFAULT_FIELD'=230 +'DEFAULT_OPERATOR'=231 +'ENABLE_POSITION_INCREMENTS'=232 +'FLAGS'=233 +'FUZZY_MAX_EXPANSIONS'=234 +'FUZZY_PREFIX_LENGTH'=235 +'FUZZY_TRANSPOSITIONS'=236 +'FUZZY_REWRITE'=237 +'FUZZINESS'=238 +'LENIENT'=239 +'LOW_FREQ_OPERATOR'=240 +'MAX_DETERMINIZED_STATES'=241 +'MAX_EXPANSIONS'=242 +'MINIMUM_SHOULD_MATCH'=243 +'OPERATOR'=244 +'PHRASE_SLOP'=245 +'PREFIX_LENGTH'=246 +'QUOTE_ANALYZER'=247 +'QUOTE_FIELD_SUFFIX'=248 +'REWRITE'=249 +'SLOP'=250 +'TIE_BREAKER'=251 +'TYPE'=252 +'ZERO_TERMS_QUERY'=253 +'SPAN'=254 +'MS'=255 +'S'=256 +'M'=257 +'H'=258 +'W'=259 +'Q'=260 +'Y'=261 diff --git a/dashboards-observability/common/query_manager/antlr/grammar/OpenSearchPPLLexer.g4 b/dashboards-observability/common/query_manager/antlr/grammar/OpenSearchPPLLexer.g4 new file mode 100644 index 000000000..c30967a77 --- /dev/null +++ b/dashboards-observability/common/query_manager/antlr/grammar/OpenSearchPPLLexer.g4 @@ -0,0 +1,333 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + + +lexer grammar OpenSearchPPLLexer; + +channels { WHITESPACE, ERRORCHANNEL } + + +// COMMAND KEYWORDS +SEARCH: 'SEARCH'; +FROM: 'FROM'; +WHERE: 'WHERE'; +FIELDS: 'FIELDS'; +RENAME: 'RENAME'; +STATS: 'STATS'; +DEDUP: 'DEDUP'; +SORT: 'SORT'; +EVAL: 'EVAL'; +HEAD: 'HEAD'; +TOP: 'TOP'; +RARE: 'RARE'; +PARSE: 'PARSE'; +KMEANS: 'KMEANS'; +AD: 'AD'; + +// COMMAND ASSIST KEYWORDS +AS: 'AS'; +BY: 'BY'; +SOURCE: 'SOURCE'; +INDEX: 'INDEX'; +D: 'D'; +DESC: 'DESC'; + +// CLAUSE KEYWORDS +SORTBY: 'SORTBY'; + +// FIELD KEYWORDS +AUTO: 'AUTO'; +STR: 'STR'; +IP: 'IP'; +NUM: 'NUM'; + +// ARGUMENT KEYWORDS +KEEPEMPTY: 'KEEPEMPTY'; +CONSECUTIVE: 'CONSECUTIVE'; +DEDUP_SPLITVALUES: 'DEDUP_SPLITVALUES'; +PARTITIONS: 'PARTITIONS'; +ALLNUM: 'ALLNUM'; +DELIM: 'DELIM'; +CENTROIDS: 'CENTROIDS'; +ITERATIONS: 'ITERATIONS'; +DISTANCE_TYPE: 'DISTANCE_TYPE'; +NUMBER_OF_TREES: 'NUMBER_OF_TREES'; +SHINGLE_SIZE: 'SHINGLE_SIZE'; +SAMPLE_SIZE: 'SAMPLE_SIZE'; +OUTPUT_AFTER: 'OUTPUT_AFTER'; +TIME_DECAY: 'TIME_DECAY'; +ANOMALY_RATE: 'ANOMALY_RATE'; +TIME_FIELD: 'TIME_FIELD'; +TIME_ZONE: 'TIME_ZONE'; +TRAINING_DATA_SIZE: 'TRAINING_DATA_SIZE'; +ANOMALY_SCORE_THRESHOLD: 'ANOMALY_SCORE_THRESHOLD'; + +// COMPARISON FUNCTION KEYWORDS +CASE: 'CASE'; +IN: 'IN'; + +// LOGICAL KEYWORDS +NOT: 'NOT'; +OR: 'OR'; +AND: 'AND'; +XOR: 'XOR'; +TRUE: 'TRUE'; +FALSE: 'FALSE'; +REGEXP: 'REGEXP'; + +// DATETIME, INTERVAL AND UNIT KEYWORDS +DATETIME: 'DATETIME'; +INTERVAL: 'INTERVAL'; +MICROSECOND: 'MICROSECOND'; +MILLISECOND: 'MILLISECOND'; +SECOND: 'SECOND'; +MINUTE: 'MINUTE'; +HOUR: 'HOUR'; +DAY: 'DAY'; +WEEK: 'WEEK'; +MONTH: 'MONTH'; +QUARTER: 'QUARTER'; +YEAR: 'YEAR'; +SECOND_MICROSECOND: 'SECOND_MICROSECOND'; +MINUTE_MICROSECOND: 'MINUTE_MICROSECOND'; +MINUTE_SECOND: 'MINUTE_SECOND'; +HOUR_MICROSECOND: 'HOUR_MICROSECOND'; +HOUR_SECOND: 'HOUR_SECOND'; +HOUR_MINUTE: 'HOUR_MINUTE'; +DAY_MICROSECOND: 'DAY_MICROSECOND'; +DAY_SECOND: 'DAY_SECOND'; +DAY_MINUTE: 'DAY_MINUTE'; +DAY_HOUR: 'DAY_HOUR'; +YEAR_MONTH: 'YEAR_MONTH'; + +// DATASET TYPES +DATAMODEL: 'DATAMODEL'; +LOOKUP: 'LOOKUP'; +SAVEDSEARCH: 'SAVEDSEARCH'; + +// CONVERTED DATA TYPES +INT: 'INT'; +INTEGER: 'INTEGER'; +DOUBLE: 'DOUBLE'; +LONG: 'LONG'; +FLOAT: 'FLOAT'; +STRING: 'STRING'; +BOOLEAN: 'BOOLEAN'; + +// SPECIAL CHARACTERS AND OPERATORS +PIPE: '|'; +COMMA: ','; +DOT: '.'; +EQUAL: '='; +GREATER: '>'; +LESS: '<'; +NOT_GREATER: '<' '='; +NOT_LESS: '>' '='; +NOT_EQUAL: '!' '='; +PLUS: '+'; +MINUS: '-'; +STAR: '*'; +DIVIDE: '/'; +MODULE: '%'; +EXCLAMATION_SYMBOL: '!'; +COLON: ':'; +LT_PRTHS: '('; +RT_PRTHS: ')'; +LT_SQR_PRTHS: '['; +RT_SQR_PRTHS: ']'; +SINGLE_QUOTE: '\''; +DOUBLE_QUOTE: '"'; +BACKTICK: '`'; + +// Operators. Bit + +BIT_NOT_OP: '~'; +BIT_AND_OP: '&'; +BIT_XOR_OP: '^'; + +// AGGREGATIONS +AVG: 'AVG'; +COUNT: 'COUNT'; +DISTINCT_COUNT: 'DISTINCT_COUNT'; +ESTDC: 'ESTDC'; +ESTDC_ERROR: 'ESTDC_ERROR'; +MAX: 'MAX'; +MEAN: 'MEAN'; +MEDIAN: 'MEDIAN'; +MIN: 'MIN'; +MODE: 'MODE'; +RANGE: 'RANGE'; +STDEV: 'STDEV'; +STDEVP: 'STDEVP'; +SUM: 'SUM'; +SUMSQ: 'SUMSQ'; +VAR_SAMP: 'VAR_SAMP'; +VAR_POP: 'VAR_POP'; +STDDEV_SAMP: 'STDDEV_SAMP'; +STDDEV_POP: 'STDDEV_POP'; +PERCENTILE: 'PERCENTILE'; +FIRST: 'FIRST'; +LAST: 'LAST'; +LIST: 'LIST'; +VALUES: 'VALUES'; +EARLIEST: 'EARLIEST'; +EARLIEST_TIME: 'EARLIEST_TIME'; +LATEST: 'LATEST'; +LATEST_TIME: 'LATEST_TIME'; +PER_DAY: 'PER_DAY'; +PER_HOUR: 'PER_HOUR'; +PER_MINUTE: 'PER_MINUTE'; +PER_SECOND: 'PER_SECOND'; +RATE: 'RATE'; +SPARKLINE: 'SPARKLINE'; +C: 'C'; +DC: 'DC'; + +// BASIC FUNCTIONS +ABS: 'ABS'; +CEIL: 'CEIL'; +CEILING: 'CEILING'; +CONV: 'CONV'; +CRC32: 'CRC32'; +E: 'E'; +EXP: 'EXP'; +FLOOR: 'FLOOR'; +LN: 'LN'; +LOG: 'LOG'; +LOG10: 'LOG10'; +LOG2: 'LOG2'; +MOD: 'MOD'; +PI: 'PI'; +POW: 'POW'; +POWER: 'POWER'; +RAND: 'RAND'; +ROUND: 'ROUND'; +SIGN: 'SIGN'; +SQRT: 'SQRT'; +TRUNCATE: 'TRUNCATE'; + +// TRIGONOMETRIC FUNCTIONS +ACOS: 'ACOS'; +ASIN: 'ASIN'; +ATAN: 'ATAN'; +ATAN2: 'ATAN2'; +COS: 'COS'; +COT: 'COT'; +DEGREES: 'DEGREES'; +RADIANS: 'RADIANS'; +SIN: 'SIN'; +TAN: 'TAN'; + +// DATE AND TIME FUNCTIONS +ADDDATE: 'ADDDATE'; +DATE: 'DATE'; +DATE_ADD: 'DATE_ADD'; +DATE_SUB: 'DATE_SUB'; +DAYOFMONTH: 'DAYOFMONTH'; +DAYOFWEEK: 'DAYOFWEEK'; +DAYOFYEAR: 'DAYOFYEAR'; +DAYNAME: 'DAYNAME'; +FROM_DAYS: 'FROM_DAYS'; +MONTHNAME: 'MONTHNAME'; +SUBDATE: 'SUBDATE'; +TIME: 'TIME'; +TIME_TO_SEC: 'TIME_TO_SEC'; +TIMESTAMP: 'TIMESTAMP'; +DATE_FORMAT: 'DATE_FORMAT'; +TO_DAYS: 'TO_DAYS'; + +// TEXT FUNCTIONS +SUBSTR: 'SUBSTR'; +SUBSTRING: 'SUBSTRING'; +LTRIM: 'LTRIM'; +RTRIM: 'RTRIM'; +TRIM: 'TRIM'; +TO: 'TO'; +LOWER: 'LOWER'; +UPPER: 'UPPER'; +CONCAT: 'CONCAT'; +CONCAT_WS: 'CONCAT_WS'; +LENGTH: 'LENGTH'; +STRCMP: 'STRCMP'; +RIGHT: 'RIGHT'; +LEFT: 'LEFT'; +ASCII: 'ASCII'; +LOCATE: 'LOCATE'; +REPLACE: 'REPLACE'; +CAST: 'CAST'; + +// BOOL FUNCTIONS +LIKE: 'LIKE'; +ISNULL: 'ISNULL'; +ISNOTNULL: 'ISNOTNULL'; + +// FLOWCONTROL FUNCTIONS +IFNULL: 'IFNULL'; +NULLIF: 'NULLIF'; +IF: 'IF'; + +// RELEVANCE FUNCTIONS AND PARAMETERS +MATCH: 'MATCH'; +MATCH_PHRASE: 'MATCH_PHRASE'; +SIMPLE_QUERY_STRING: 'SIMPLE_QUERY_STRING'; + +ALLOW_LEADING_WILDCARD: 'ALLOW_LEADING_WILDCARD'; +ANALYZE_WILDCARD: 'ANALYZE_WILDCARD'; +ANALYZER: 'ANALYZER'; +AUTO_GENERATE_SYNONYMS_PHRASE_QUERY:'AUTO_GENERATE_SYNONYMS_PHRASE_QUERY'; +BOOST: 'BOOST'; +CUTOFF_FREQUENCY: 'CUTOFF_FREQUENCY'; +DEFAULT_FIELD: 'DEFAULT_FIELD'; +DEFAULT_OPERATOR: 'DEFAULT_OPERATOR'; +ENABLE_POSITION_INCREMENTS: 'ENABLE_POSITION_INCREMENTS'; +FLAGS: 'FLAGS'; +FUZZY_MAX_EXPANSIONS: 'FUZZY_MAX_EXPANSIONS'; +FUZZY_PREFIX_LENGTH: 'FUZZY_PREFIX_LENGTH'; +FUZZY_TRANSPOSITIONS: 'FUZZY_TRANSPOSITIONS'; +FUZZY_REWRITE: 'FUZZY_REWRITE'; +FUZZINESS: 'FUZZINESS'; +LENIENT: 'LENIENT'; +LOW_FREQ_OPERATOR: 'LOW_FREQ_OPERATOR'; +MAX_DETERMINIZED_STATES: 'MAX_DETERMINIZED_STATES'; +MAX_EXPANSIONS: 'MAX_EXPANSIONS'; +MINIMUM_SHOULD_MATCH: 'MINIMUM_SHOULD_MATCH'; +OPERATOR: 'OPERATOR'; +PHRASE_SLOP: 'PHRASE_SLOP'; +PREFIX_LENGTH: 'PREFIX_LENGTH'; +QUOTE_ANALYZER: 'QUOTE_ANALYZER'; +QUOTE_FIELD_SUFFIX: 'QUOTE_FIELD_SUFFIX'; +REWRITE: 'REWRITE'; +SLOP: 'SLOP'; +TIE_BREAKER: 'TIE_BREAKER'; +TYPE: 'TYPE'; +ZERO_TERMS_QUERY: 'ZERO_TERMS_QUERY'; + +// SPAN KEYWORDS +SPAN: 'SPAN'; +MS: 'MS'; +S: 'S'; +M: 'M'; +H: 'H'; +W: 'W'; +Q: 'Q'; +Y: 'Y'; + + +// LITERALS AND VALUES +//STRING_LITERAL: DQUOTA_STRING | SQUOTA_STRING | BQUOTA_STRING; +ID: ID_LITERAL; +INTEGER_LITERAL: DEC_DIGIT+; +DECIMAL_LITERAL: (DEC_DIGIT+)? '.' DEC_DIGIT+; + +fragment DATE_SUFFIX: ([\-.][*0-9]+)*; +fragment ID_LITERAL: [@*A-Z]+?[*A-Z_\-0-9]*; +ID_DATE_SUFFIX: ID_LITERAL DATE_SUFFIX; +DQUOTA_STRING: '"' ( '\\'. | '""' | ~('"'| '\\') )* '"'; +SQUOTA_STRING: '\'' ('\\'. | '\'\'' | ~('\'' | '\\'))* '\''; +BQUOTA_STRING: '`' ( '\\'. | '``' | ~('`'|'\\'))* '`'; +fragment DEC_DIGIT: [0-9]; + + +ERROR_RECOGNITION: . -> channel(ERRORCHANNEL); \ No newline at end of file diff --git a/dashboards-observability/common/query_manager/antlr/grammar/OpenSearchPPLParser.g4 b/dashboards-observability/common/query_manager/antlr/grammar/OpenSearchPPLParser.g4 new file mode 100644 index 000000000..de96295f9 --- /dev/null +++ b/dashboards-observability/common/query_manager/antlr/grammar/OpenSearchPPLParser.g4 @@ -0,0 +1,475 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + + + +parser grammar OpenSearchPPLParser; +options { tokenVocab=OpenSearchPPLLexer; } + +root + : pplStatement? EOF + ; + +/** statement */ +pplStatement + : searchCommand (PIPE commands)* + ; + +/** commands */ +commands + : whereCommand | fieldsCommand | renameCommand | statsCommand | dedupCommand | sortCommand | evalCommand | headCommand + | topCommand | rareCommand | parseCommand | kmeansCommand | adCommand; + +searchCommand + : (SEARCH)? fromClause #searchFrom + | (SEARCH)? fromClause logicalExpression #searchFromFilter + | (SEARCH)? logicalExpression fromClause #searchFilterFrom + ; + +whereCommand + : WHERE logicalExpression + ; + +fieldsCommand + : FIELDS (PLUS | MINUS)? fieldList + ; + +renameCommand + : RENAME renameClasue (COMMA renameClasue)* + ; + +statsCommand + : STATS + (PARTITIONS EQUAL partitions=integerLiteral)? + (ALLNUM EQUAL allnum=booleanLiteral)? + (DELIM EQUAL delim=stringLiteral)? + statsAggTerm (COMMA statsAggTerm)* + (statsByClause)? + (DEDUP_SPLITVALUES EQUAL dedupsplit=booleanLiteral)? + ; + +dedupCommand + : DEDUP + (number=integerLiteral)? + fieldList + (KEEPEMPTY EQUAL keepempty=booleanLiteral)? + (CONSECUTIVE EQUAL consecutive=booleanLiteral)? + ; + +sortCommand + : SORT sortbyClause + ; + +evalCommand + : EVAL evalClause (COMMA evalClause)* + ; + +headCommand + : HEAD + (number=integerLiteral)? + (FROM from=integerLiteral)? + ; + +topCommand + : TOP + (number=integerLiteral)? + fieldList + (byClause)? + ; + +rareCommand + : RARE + fieldList + (byClause)? + ; + +parseCommand + : PARSE expression pattern + ; + +kmeansCommand + : KMEANS (kmeansParameter)* + ; + +kmeansParameter + : (CENTROIDS EQUAL centroids=integerLiteral) + | (ITERATIONS EQUAL iterations=integerLiteral) + | (DISTANCE_TYPE EQUAL distance_type=stringLiteral) + ; + +adCommand + : AD (adParameter)* + ; + +adParameter + : (NUMBER_OF_TREES EQUAL number_of_trees=integerLiteral) + | (SHINGLE_SIZE EQUAL shingle_size=integerLiteral) + | (SAMPLE_SIZE EQUAL sample_size=integerLiteral) + | (OUTPUT_AFTER EQUAL output_after=integerLiteral) + | (TIME_DECAY EQUAL time_decay=decimalLiteral) + | (ANOMALY_RATE EQUAL anomaly_rate=decimalLiteral) + | (TIME_FIELD EQUAL time_field=stringLiteral) + | (DATE_FORMAT EQUAL date_format=stringLiteral) + | (TIME_ZONE EQUAL time_zone=stringLiteral) + | (TRAINING_DATA_SIZE EQUAL training_data_size=integerLiteral) + | (ANOMALY_SCORE_THRESHOLD EQUAL anomaly_score_threshold=decimalLiteral) + ; + +/** clauses */ +fromClause + : SOURCE EQUAL tableSource (COMMA tableSource)* + | INDEX EQUAL tableSource (COMMA tableSource)* + ; + +renameClasue + : orignalField=wcFieldExpression AS renamedField=wcFieldExpression + ; + +byClause + : BY fieldList + ; + +statsByClause + : BY fieldList + | BY bySpanClause + | BY bySpanClause COMMA fieldList + ; + +bySpanClause + : spanClause (AS alias=qualifiedName)? + ; + +spanClause + : SPAN LT_PRTHS fieldExpression COMMA value=literalValue (unit=timespanUnit)? RT_PRTHS + ; + +sortbyClause + : sortField (COMMA sortField)* + ; + +evalClause + : fieldExpression EQUAL expression + ; + +/** aggregation terms */ +statsAggTerm + : statsFunction (AS alias=wcFieldExpression)? + ; + +/** aggregation functions */ +statsFunction + : statsFunctionName LT_PRTHS valueExpression RT_PRTHS #statsFunctionCall + | COUNT LT_PRTHS RT_PRTHS #countAllFunctionCall + | (DISTINCT_COUNT | DC) LT_PRTHS valueExpression RT_PRTHS #distinctCountFunctionCall + | percentileAggFunction #percentileAggFunctionCall + ; + +statsFunctionName + : AVG | COUNT | SUM | MIN | MAX | VAR_SAMP | VAR_POP | STDDEV_SAMP | STDDEV_POP + ; + +percentileAggFunction + : PERCENTILE LESS value=integerLiteral GREATER LT_PRTHS aggField=fieldExpression RT_PRTHS + ; + +/** expressions */ +expression + : logicalExpression + | comparisonExpression + | valueExpression + ; + +logicalExpression + : comparisonExpression #comparsion + | NOT logicalExpression #logicalNot + | left=logicalExpression OR right=logicalExpression #logicalOr + | left=logicalExpression (AND)? right=logicalExpression #logicalAnd + | left=logicalExpression XOR right=logicalExpression #logicalXor + | booleanExpression #booleanExpr + | relevanceExpression #relevanceExpr + ; + +comparisonExpression + : left=valueExpression comparisonOperator right=valueExpression #compareExpr + | valueExpression IN valueList #inExpr + ; + +valueExpression + : left=valueExpression binaryOperator right=valueExpression #binaryArithmetic + | LT_PRTHS left=valueExpression binaryOperator + right=valueExpression RT_PRTHS #parentheticBinaryArithmetic + | primaryExpression #valueExpressionDefault + ; + +primaryExpression + : evalFunctionCall + | dataTypeFunctionCall + | fieldExpression + | literalValue + ; + +booleanExpression + : booleanFunctionCall + ; + +relevanceExpression + : singleFieldRelevanceFunction | multiFieldRelevanceFunction + ; + +// Field is a single column +singleFieldRelevanceFunction + : singleFieldRelevanceFunctionName LT_PRTHS + field=relevanceField COMMA query=relevanceQuery + (COMMA relevanceArg)* RT_PRTHS + ; + +// Field is a list of columns +multiFieldRelevanceFunction + : multiFieldRelevanceFunctionName LT_PRTHS + LT_SQR_PRTHS field=relevanceFieldAndWeight (COMMA field=relevanceFieldAndWeight)* RT_SQR_PRTHS + COMMA query=relevanceQuery (COMMA relevanceArg)* RT_PRTHS + ; + +/** tables */ +tableSource + : qualifiedName + | ID_DATE_SUFFIX + ; + +/** fields */ +fieldList + : fieldExpression (COMMA fieldExpression)* + ; + +wcFieldList + : wcFieldExpression (COMMA wcFieldExpression)* + ; + +sortField + : (PLUS | MINUS)? sortFieldExpression + ; + +sortFieldExpression + : fieldExpression + | AUTO LT_PRTHS fieldExpression RT_PRTHS + | STR LT_PRTHS fieldExpression RT_PRTHS + | IP LT_PRTHS fieldExpression RT_PRTHS + | NUM LT_PRTHS fieldExpression RT_PRTHS + ; + +fieldExpression + : qualifiedName + ; + +wcFieldExpression + : wcQualifiedName + ; + +/** functions */ +evalFunctionCall + : evalFunctionName LT_PRTHS functionArgs RT_PRTHS + ; + +/** cast function */ +dataTypeFunctionCall + : CAST LT_PRTHS expression AS convertedDataType RT_PRTHS + ; + +/** boolean functions */ +booleanFunctionCall + : conditionFunctionBase LT_PRTHS functionArgs RT_PRTHS + ; + +convertedDataType + : typeName=DATE + | typeName=TIME + | typeName=TIMESTAMP + | typeName=INT + | typeName=INTEGER + | typeName=DOUBLE + | typeName=LONG + | typeName=FLOAT + | typeName=STRING + | typeName=BOOLEAN + ; + +evalFunctionName + : mathematicalFunctionBase + | dateAndTimeFunctionBase + | textFunctionBase + | conditionFunctionBase + ; + +functionArgs + : (functionArg (COMMA functionArg)*)? + ; + +functionArg + : valueExpression + ; + +relevanceArg + : relevanceArgName EQUAL relevanceArgValue + ; + +relevanceArgName + : ALLOW_LEADING_WILDCARD | ANALYZER | ANALYZE_WILDCARD | AUTO_GENERATE_SYNONYMS_PHRASE_QUERY + | BOOST | CUTOFF_FREQUENCY | DEFAULT_FIELD | DEFAULT_OPERATOR | ENABLE_POSITION_INCREMENTS + | FIELDS | FLAGS | FUZZINESS | FUZZY_MAX_EXPANSIONS | FUZZY_PREFIX_LENGTH | FUZZY_REWRITE + | FUZZY_TRANSPOSITIONS | LENIENT | LOW_FREQ_OPERATOR | MAX_DETERMINIZED_STATES + | MAX_EXPANSIONS | MINIMUM_SHOULD_MATCH | OPERATOR | PHRASE_SLOP | PREFIX_LENGTH + | QUOTE_ANALYZER | QUOTE_FIELD_SUFFIX | REWRITE | SLOP | TIE_BREAKER | TIME_ZONE | TYPE + | ZERO_TERMS_QUERY + ; + +relevanceFieldAndWeight + : field=relevanceField + | field=relevanceField weight=relevanceFieldWeight + | field=relevanceField BIT_XOR_OP weight=relevanceFieldWeight + ; + +relevanceFieldWeight + : integerLiteral + | decimalLiteral + ; + +relevanceField + : qualifiedName + | stringLiteral + ; + +relevanceQuery + : relevanceArgValue + ; + +relevanceArgValue + : qualifiedName + | literalValue + ; + +mathematicalFunctionBase + : ABS | CEIL | CEILING | CONV | CRC32 | E | EXP | FLOOR | LN | LOG | LOG10 | LOG2 | MOD | PI |POW | POWER + | RAND | ROUND | SIGN | SQRT | TRUNCATE + | trigonometricFunctionName + ; + +trigonometricFunctionName + : ACOS | ASIN | ATAN | ATAN2 | COS | COT | DEGREES | RADIANS | SIN | TAN + ; + +dateAndTimeFunctionBase + : ADDDATE | DATE | DATE_ADD | DATE_SUB | DAY | DAYNAME | DAYOFMONTH | DAYOFWEEK | DAYOFYEAR | FROM_DAYS + | HOUR | MICROSECOND | MINUTE | MONTH | MONTHNAME | QUARTER | SECOND | SUBDATE | TIME | TIME_TO_SEC + | TIMESTAMP | TO_DAYS | YEAR | WEEK | DATE_FORMAT + ; + +/** condition function return boolean value */ +conditionFunctionBase + : LIKE + | IF | ISNULL | ISNOTNULL | IFNULL | NULLIF + ; + +textFunctionBase + : SUBSTR | SUBSTRING | TRIM | LTRIM | RTRIM | LOWER | UPPER | CONCAT | CONCAT_WS | LENGTH | STRCMP + | RIGHT | LEFT | ASCII | LOCATE | REPLACE + ; + +/** operators */ +comparisonOperator + : EQUAL | NOT_EQUAL | LESS | NOT_LESS | GREATER | NOT_GREATER | REGEXP + ; + +binaryOperator + : PLUS | MINUS | STAR | DIVIDE | MODULE + ; + + +singleFieldRelevanceFunctionName + : MATCH + | MATCH_PHRASE + ; + +multiFieldRelevanceFunctionName + : SIMPLE_QUERY_STRING + ; + +/** literals and values*/ +literalValue + : intervalLiteral + | stringLiteral + | integerLiteral + | decimalLiteral + | booleanLiteral + ; + +intervalLiteral + : INTERVAL valueExpression intervalUnit + ; + +stringLiteral + : DQUOTA_STRING | SQUOTA_STRING + ; + +integerLiteral + : (PLUS | MINUS)? INTEGER_LITERAL + ; + +decimalLiteral + : (PLUS | MINUS)? DECIMAL_LITERAL + ; + +booleanLiteral + : TRUE | FALSE + ; + +pattern + : stringLiteral + ; + +intervalUnit + : MICROSECOND | SECOND | MINUTE | HOUR | DAY | WEEK | MONTH | QUARTER | YEAR | SECOND_MICROSECOND + | MINUTE_MICROSECOND | MINUTE_SECOND | HOUR_MICROSECOND | HOUR_SECOND | HOUR_MINUTE | DAY_MICROSECOND + | DAY_SECOND | DAY_MINUTE | DAY_HOUR | YEAR_MONTH + ; + +timespanUnit + : MS | S | M | H | D | W | Q | Y + | MILLISECOND | SECOND | MINUTE | HOUR | DAY | WEEK | MONTH | QUARTER | YEAR + ; + + +valueList + : LT_PRTHS literalValue (COMMA literalValue)* RT_PRTHS + ; + +qualifiedName + : ident (DOT ident)* #identsAsQualifiedName + ; + +wcQualifiedName + : wildcard (DOT wildcard)* #identsAsWildcardQualifiedName + ; + +ident + : (DOT)? ID + | BACKTICK ident BACKTICK + | BQUOTA_STRING + | keywordsCanBeId + ; + +wildcard + : ident (MODULE ident)* (MODULE)? + | SINGLE_QUOTE wildcard SINGLE_QUOTE + | DOUBLE_QUOTE wildcard DOUBLE_QUOTE + | BACKTICK wildcard BACKTICK + ; + +keywordsCanBeId + : D // OD SQL and ODBC special + | statsFunctionName + | TIMESTAMP | DATE | TIME + | FIRST | LAST + | timespanUnit | SPAN + ; \ No newline at end of file diff --git a/dashboards-observability/common/query_manager/antlr/ppl_syntax_parser.ts b/dashboards-observability/common/query_manager/antlr/ppl_syntax_parser.ts new file mode 100644 index 000000000..6f62bce1c --- /dev/null +++ b/dashboards-observability/common/query_manager/antlr/ppl_syntax_parser.ts @@ -0,0 +1,30 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { CharStreams, CommonTokenStream } from 'antlr4ts'; +import { CaseInsensitiveCharStream } from './adaptors/case_insensitive_char_stream'; +import { OpenSearchPPLLexer } from './output/OpenSearchPPLLexer'; +import { OpenSearchPPLParser } from './output/OpenSearchPPLParser'; + +/** + * PPL Syntax Parser. + */ +export class PPLSyntaxParser { + /** + * Analyze the query syntax. + */ + + parse(query: string) { + return this.createParser(this.createLexer(query)); + } + + createLexer(query: string) { + return new OpenSearchPPLLexer(new CaseInsensitiveCharStream(CharStreams.fromString(query))); + } + + createParser(lexer: OpenSearchPPLLexer) { + return new OpenSearchPPLParser(new CommonTokenStream(lexer)); + } +} diff --git a/dashboards-observability/common/query_manager/ast/builder/query_builder.ts b/dashboards-observability/common/query_manager/ast/builder/query_builder.ts new file mode 100644 index 000000000..a6b6494c0 --- /dev/null +++ b/dashboards-observability/common/query_manager/ast/builder/query_builder.ts @@ -0,0 +1,8 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export interface QueryBuilder { + build: () => T; +} diff --git a/dashboards-observability/common/query_manager/ast/builder/stats_ast_builder.ts b/dashboards-observability/common/query_manager/ast/builder/stats_ast_builder.ts new file mode 100644 index 000000000..6c33b37a1 --- /dev/null +++ b/dashboards-observability/common/query_manager/ast/builder/stats_ast_builder.ts @@ -0,0 +1,228 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { AbstractParseTreeVisitor } from 'antlr4ts/tree/AbstractParseTreeVisitor'; +import { + RootContext, + PplStatementContext, + CommandsContext, + StatsCommandContext, + BooleanLiteralContext, + BySpanClauseContext, + FieldExpressionContext, + FieldListContext, + IntegerLiteralContext, + LiteralValueContext, + QualifiedNameContext, + SpanClauseContext, + StatsAggTermContext, + StatsByClauseContext, + StatsFunctionContext, + StatsFunctionNameContext, + StringLiteralContext, + TimespanUnitContext, + ValueExpressionContext, + WcFieldExpressionContext, +} from '../../antlr/output/OpenSearchPPLParser'; +import { OpenSearchPPLParserVisitor } from '../../antlr/output/OpenSearchPPLParserVisitor'; +import { PPLNode } from '../node'; +import { Aggregations } from '../tree/aggragations'; +import { + AggregateFunction, + AggregateTerm, + GroupBy, + Field, + Span, + SpanExpression, +} from '../expression'; + +type VisitResult = PPLNode | Array | string; + +export class StatsAstBuilder + extends AbstractParseTreeVisitor + implements OpenSearchPPLParserVisitor { + protected defaultResult(): PPLNode { + return new PPLNode('default', [] as Array); + } + + visitRoot(ctx: RootContext) { + if (!ctx.pplStatement()) return this.defaultResult(); + return this.visitChildren(ctx.pplStatement()!); + } + + visitPplStatement(ctx: PplStatementContext): PPLNode { + let statsTree: VisitResult = this.defaultResult(); + ctx.commands().map((pplCommandContext) => { + if (this.visitChildren(pplCommandContext).getName() === 'stats_command') + statsTree = this.visitChildren(pplCommandContext); + }); + return statsTree; + } + + visitCommands(ctx: CommandsContext) { + if (ctx.statsCommand()) { + return this.visitStatsCommand(ctx.statsCommand()!); + } + return this.defaultResult(); + } + + /** + * Stats command + */ + visitStatsCommand(ctx: StatsCommandContext): PPLNode { + return new Aggregations( + 'stats_command', + [] as Array, + ctx.PARTITIONS() && ctx.integerLiteral() + ? { + keyword: ctx.PARTITIONS()?.text, + sign: '=', + value: ctx.integerLiteral()?.text, + } + : {}, // visit partitions partial + ctx.ALLNUM() && ctx.booleanLiteral() + ? { + keyword: ctx.ALLNUM()?.text, + sign: '=', + value: this.visitBooleanLiteral(ctx.booleanLiteral()[0]), + } + : {}, // visit allnum partial + ctx.DELIM() && ctx.stringLiteral() + ? { + keyword: ctx.DELIM()?.text, + sign: '=', + value: this.visitStringLiteral(ctx.stringLiteral()!), + } + : '', // visit delim partial + ctx.statsAggTerm().map((aggTermAlternative) => this.visitStatsAggTerm(aggTermAlternative)), // visit statsAggTerm + ctx.statsByClause() ? this.visitStatsByClause(ctx.statsByClause()!) : ({} as GroupBy), // visit group list + ctx.DEDUP_SPLITVALUES() && ctx.booleanLiteral() + ? { + keyword: ctx.DEDUP_SPLITVALUES()?.text, + sign: '=', + value: this.visitBooleanLiteral(ctx.booleanLiteral()[1]), + } + : '', // visit dedup split value + { + start: ctx.start.startIndex, + end: ctx.stop?.stopIndex, + } // stats start/end indices in query for later query concatenation + ); + } + + visitIntegerLiteral(ctx: IntegerLiteralContext): string { + return ctx.text; + } + + visitBooleanLiteral(ctx: BooleanLiteralContext): string { + return ctx.text; + } + + visitStringLiteral(ctx: StringLiteralContext): string { + return ctx.text; + } + + visitStatsAggTerm(ctx: StatsAggTermContext): PPLNode { + return new AggregateTerm( + 'stats_agg_term', + [] as Array, + this.visitStatsFunction(ctx.statsFunction()), + ctx.wcFieldExpression() ? this.visitWcFieldExpression(ctx.wcFieldExpression()!) : '' + ); + } + + visitWcFieldExpression(ctx: WcFieldExpressionContext): string { + // return only text from here to all its chilren for now + return ctx.wcQualifiedName().text; + } + + visitStatsByClause(ctx: StatsByClauseContext): PPLNode { + return new GroupBy( + 'stats_by_clause', + [] as Array, + ctx.fieldList() ? this.visitFieldList(ctx.fieldList()!) : [], + ctx.bySpanClause() ? this.visitBySpanClause(ctx.bySpanClause()!) : this.defaultResult() + ); + } + + visitBySpanClause(ctx: BySpanClauseContext): PPLNode { + return new Span( + 'span_clause', + [] as Array, + this.visitSpanClause(ctx.spanClause()), + ctx.qualifiedName() ? this.visitQualifiedName(ctx.qualifiedName()!) : '' + ); + } + + visitSpanClause(ctx: SpanClauseContext): PPLNode { + return new SpanExpression( + 'span_expression', + [] as Array, + this.visitFieldExpression(ctx.fieldExpression()), + this.visitLiteralValue(ctx.literalValue()), + ctx.timespanUnit() ? this.visitTimespanUnit(ctx.timespanUnit()!) : '' + ); + } + + visitLiteralValue(ctx: LiteralValueContext): string { + return ctx.text; + } + + visitTimespanUnit(ctx: TimespanUnitContext): string { + return ctx.text; + } + + visitStatsFunction(ctx: StatsFunctionContext): PPLNode { + let funcName = ''; + let valueExpr = ''; + + if (typeof ctx.valueExpression === 'function') { + valueExpr = this.visitValueExpression(ctx.valueExpression()); + if (typeof ctx.statsFunctionName === 'function') { + funcName = this.visitStatsFunctionName(ctx.statsFunctionName()); + } else { + funcName = ctx.DISTINCT_COUNT() ? ctx.DISTINCT_COUNT().text : ctx.DC().text; + } + } else if (typeof ctx.percentileAggFunction === 'function') { + // for now just return plain text + } else { + funcName = ctx.COUNT().text; + } + + return new AggregateFunction( + 'stats_function', + [] as Array, + funcName, + valueExpr, + typeof ctx.percentileAggFunction === 'function' ? ctx.text : '' + ); + } + + visitValueExpression(ctx: ValueExpressionContext): string { + return ctx.text; + } + + visitStatsFunctionName(ctx: StatsFunctionNameContext): string { + return ctx.text; + } + + visitFieldList(ctx: FieldListContext): Array { + return ctx.fieldExpression().map((fieldExprAlternative) => { + return new Field( + 'field_expression', + [] as Array, + this.visitFieldExpression(fieldExprAlternative) + ); + }); + } + + visitFieldExpression(ctx: FieldExpressionContext): string { + return this.visitQualifiedName(ctx.qualifiedName()); + } + + visitQualifiedName(ctx: QualifiedNameContext): string { + return ctx.text; + } +} diff --git a/dashboards-observability/common/query_manager/ast/builder/stats_builder.ts b/dashboards-observability/common/query_manager/ast/builder/stats_builder.ts new file mode 100644 index 000000000..201431b27 --- /dev/null +++ b/dashboards-observability/common/query_manager/ast/builder/stats_builder.ts @@ -0,0 +1,135 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { isEmpty } from 'lodash'; +import { QueryBuilder } from './query_builder'; +import { Aggregations } from '../tree/aggragations'; +import { PPLNode } from '../node'; +import { + AggregateFunction, + AggregateTerm, + Field, + GroupBy, + Span, + SpanExpression, +} from '../expression'; +import { + ExpressionChunk, + SpanChunk, + StatsAggregationChunk, + StatsAggregationFunctionChunk, + GroupByChunk, + GroupField, + statsChunk, + SpanExpressionChunk, +} from '../types'; + +export class StatsBuilder implements QueryBuilder { + constructor(private statsChunk: statsChunk) {} + + build(): Aggregations { + // return a new stats subtree + return new Aggregations( + 'stats_command', + [] as Array, + !isEmpty(this.statsChunk.partitions) ? this.buildParttions(this.statsChunk.partitions) : '', + !isEmpty(this.statsChunk.all_num) ? this.buildAllNum(this.statsChunk.all_num) : '', + !isEmpty(this.statsChunk.delim) ? this.buildDelim(this.statsChunk.delim) : '', + !isEmpty(this.statsChunk.aggregations) + ? this.buildAggList(this.statsChunk.aggregations) + : ([] as Array), + !isEmpty(this.statsChunk.groupby) + ? this.buildGroupList(this.statsChunk.groupby) + : new GroupBy('stats_by_clause', [] as Array, [], null), + !isEmpty(this.statsChunk.dedup_split_value) + ? this.buildDedupSplitValue(this.statsChunk.dedup_split_value) + : '' + ); + } + + /** + * Flags + */ + buildParttions(partitions: ExpressionChunk) { + return `${partitions.keyword} ${partitions.sign} ${partitions.value}`; + } + + buildAllNum(allNum: ExpressionChunk) { + return `${allNum.keyword} ${allNum.sign} ${allNum.value}`; + } + + buildDelim(delim: ExpressionChunk) { + return `${delim.keyword} ${delim.sign} ${delim.value}`; + } + + buildDedupSplitValue(dedupSplitvalue: ExpressionChunk) { + return `${dedupSplitvalue.keyword} ${dedupSplitvalue.sign} ${dedupSplitvalue.value}`; + } + + /** + * Aggregations + */ + buildAggList(aggregations: Array) { + return aggregations.map((aggregation) => { + return this.buildAggTerm(aggregation); + }); + } + + buildAggTerm(aggTerm: StatsAggregationChunk) { + return new AggregateTerm( + 'stats_agg_term', + [] as Array, + this.buildAggregateFunction(aggTerm.function), + aggTerm.function_alias + ); + } + + buildAggregateFunction(aggFunction: StatsAggregationFunctionChunk) { + return new AggregateFunction( + 'stats_function', + [] as Array, + aggFunction.name, + aggFunction.value_expression, + aggFunction.percentile_agg_function + ); + } + + /** + * Groups + */ + buildGroupList(groupby: GroupByChunk) { + return new GroupBy( + 'stats_by_clause', + [] as Array, + this.buildFieldList(groupby.group_fields), + groupby.span ? this.buildSpan(groupby.span) : null + ); + } + + buildFieldList(group_fields: Array) { + return group_fields.map((gf: GroupField) => { + return new Field('field_expression', [] as Array, gf.name); + }); + } + + buildSpan(span: SpanChunk) { + return new Span( + 'span_clause', + [] as Array, + this.buildeSpanExpression(span.span_expression), + span.alias + ); + } + + buildeSpanExpression(spanExpression: SpanExpressionChunk) { + return new SpanExpression( + 'span_expression', + [] as Array, + spanExpression.field, + spanExpression.literal_value, + spanExpression.time_unit + ); + } +} diff --git a/dashboards-observability/common/query_manager/ast/expression/AggregateFunction.ts b/dashboards-observability/common/query_manager/ast/expression/AggregateFunction.ts new file mode 100644 index 000000000..06c05cec6 --- /dev/null +++ b/dashboards-observability/common/query_manager/ast/expression/AggregateFunction.ts @@ -0,0 +1,37 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { PPLNode } from '../node'; + +export class AggregateFunction extends PPLNode { + constructor( + name: string, + children: Array, + private statsFunctionName: string, + private valueExpression: string, + private percentileAggFunction: string + ) { + super(name, children); + } + + getTokens() { + return { + name: this.statsFunctionName, + value_expression: this.valueExpression, + percentile_agg_function: this.percentileAggFunction, + }; + } + + toString(): string { + if (this.statsFunctionName && this.valueExpression) { + return `${this.statsFunctionName}(${this.valueExpression})`; + } else if (this.statsFunctionName) { + return `${this.statsFunctionName}()`; + } else if (this.percentileAggFunction) { + return `${this.percentileAggFunction}`; + } + return ''; + } +} diff --git a/dashboards-observability/common/query_manager/ast/expression/AggregateTerm.ts b/dashboards-observability/common/query_manager/ast/expression/AggregateTerm.ts new file mode 100644 index 000000000..a19b488d5 --- /dev/null +++ b/dashboards-observability/common/query_manager/ast/expression/AggregateTerm.ts @@ -0,0 +1,31 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { PPLNode } from '../node'; + +export class AggregateTerm extends PPLNode { + constructor( + name: string, + children: Array, + private statsFunction: PPLNode, + private alias: string + ) { + super(name, children); + } + + getTokens() { + return { + function: this.statsFunction.getTokens(), + alias: this.alias, + }; + } + + toString(): string { + if (this.alias) { + return `${this.statsFunction.toString()}${this.alias ? ` as ${this.alias}` : ''}`; + } + return `${this.statsFunction.toString()}`; + } +} diff --git a/dashboards-observability/common/query_manager/ast/expression/field.ts b/dashboards-observability/common/query_manager/ast/expression/field.ts new file mode 100644 index 000000000..3bc35ce70 --- /dev/null +++ b/dashboards-observability/common/query_manager/ast/expression/field.ts @@ -0,0 +1,20 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { PPLNode } from '../node'; + +export class Field extends PPLNode { + constructor(name: string, children: Array, private fieldExpression: string) { + super(name, children); + } + + getTokens() { + return { name: this.fieldExpression ?? '' }; + } + + toString(): string { + return this.fieldExpression ?? ''; + } +} diff --git a/dashboards-observability/common/query_manager/ast/expression/group_by.ts b/dashboards-observability/common/query_manager/ast/expression/group_by.ts new file mode 100644 index 000000000..ce6d8ffef --- /dev/null +++ b/dashboards-observability/common/query_manager/ast/expression/group_by.ts @@ -0,0 +1,31 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { PPLNode } from '../node'; +import { Field } from './field'; + +export class GroupBy extends PPLNode { + constructor( + name: string, + children: Array, + private fields: Array, + private span: PPLNode | null + ) { + super(name, children); + } + + getTokens() { + return { + group_fields: this.fields.map((field) => field.getTokens()), + span: this.span?.getTokens(), + }; + } + + toString(): string { + return `by ${this.span ? `${this.span.toString()}${this.fields.length > 0 ? ', ' : ''}` : ''}${this.fields + .map((field) => field.toString()) + .join(', ')}`; + } +} diff --git a/dashboards-observability/common/query_manager/ast/expression/index.ts b/dashboards-observability/common/query_manager/ast/expression/index.ts new file mode 100644 index 000000000..222ca12ca --- /dev/null +++ b/dashboards-observability/common/query_manager/ast/expression/index.ts @@ -0,0 +1,6 @@ +export { AggregateFunction } from './AggregateFunction'; +export { AggregateTerm } from './AggregateTerm'; +export { GroupBy } from './group_by'; +export { Span } from './span'; +export { SpanExpression } from './spanExpression'; +export { Field } from './field'; diff --git a/dashboards-observability/common/query_manager/ast/expression/span.ts b/dashboards-observability/common/query_manager/ast/expression/span.ts new file mode 100644 index 000000000..d2a570915 --- /dev/null +++ b/dashboards-observability/common/query_manager/ast/expression/span.ts @@ -0,0 +1,28 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { PPLNode } from '../node'; + +export class Span extends PPLNode { + constructor( + name: string, + children: Array, + private spanExpression: PPLNode, + private alias: string + ) { + super(name, children); + } + + getTokens() { + return { + span_expression: this.spanExpression.getTokens(), + alias: this.alias, + }; + } + + toString(): string { + return `${this.spanExpression.toString()}${this.alias ? ` as ${this.alias}` : ''}`; + } +} diff --git a/dashboards-observability/common/query_manager/ast/expression/spanExpression.ts b/dashboards-observability/common/query_manager/ast/expression/spanExpression.ts new file mode 100644 index 000000000..c3f8d15ed --- /dev/null +++ b/dashboards-observability/common/query_manager/ast/expression/spanExpression.ts @@ -0,0 +1,30 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { PPLNode } from '../node'; + +export class SpanExpression extends PPLNode { + constructor( + name: string, + children: Array, + private fieldExpression: string, + private literalValue: string, + private timeUnit: string + ) { + super(name, children); + } + + getTokens() { + return { + field: this.fieldExpression, + literal_value: this.literalValue, + time_unit: this.timeUnit, + }; + } + + toString(): string { + return `span(${this.fieldExpression}, ${this.literalValue}${this.timeUnit})`; + } +} diff --git a/dashboards-observability/common/query_manager/ast/index.ts b/dashboards-observability/common/query_manager/ast/index.ts new file mode 100644 index 000000000..eb0dbf6a7 --- /dev/null +++ b/dashboards-observability/common/query_manager/ast/index.ts @@ -0,0 +1,6 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export { PPLNode } from './node'; diff --git a/dashboards-observability/common/query_manager/ast/node.ts b/dashboards-observability/common/query_manager/ast/node.ts new file mode 100644 index 000000000..c28877369 --- /dev/null +++ b/dashboards-observability/common/query_manager/ast/node.ts @@ -0,0 +1,31 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +interface PPLNodeProps { + getName: () => string; + getChildren: () => Array; + toString: () => string; + getTokens: () => any; +} + +export class PPLNode implements PPLNodeProps { + constructor(private name: string, private children: Array) {} + + getChildren(): Array { + return this.children; + } + + getName(): string { + return this.name; + } + + toString(): string { + return ''; + } + + getTokens(): any { + return null; + } +} diff --git a/dashboards-observability/common/query_manager/ast/tree/aggragations.ts b/dashboards-observability/common/query_manager/ast/tree/aggragations.ts new file mode 100644 index 000000000..73201a2e5 --- /dev/null +++ b/dashboards-observability/common/query_manager/ast/tree/aggragations.ts @@ -0,0 +1,58 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { isEmpty } from 'lodash'; +import { PPLNode } from '../node'; +import { GroupBy } from '../expression/group_by'; + +export class Aggregations extends PPLNode { + constructor( + name: string, + children: Array, + private partitions: String, + private allNum: string, + private delim: string, + private aggExprList: Array, + private groupExprList: GroupBy, + private dedupSplitValue: string, + private indices?: { start: number; end: number } + ) { + super(name, children); + } + + getStartEndIndicesOfOriginQuery(): { start: number; end: number } { + if (this.indices === undefined) { + return { + start: -1, + end: -1, + }; + } + return { + start: this.indices.start, + end: this.indices.end, + }; + } + + getTokens() { + return { + partitions: this.partitions, + all_num: this.allNum, + delim: this.delim, + aggregations: this.aggExprList.map((aggTerm) => aggTerm.getTokens()), + groupby: this.groupExprList.getTokens(), + dedup_split_value: this.dedupSplitValue, + }; + } + + toString() { + return `stats ${!isEmpty(this.partitions) ? `${this.partitions} ` : ''}${ + !isEmpty(this.allNum) ? `${this.allNum} ` : '' + }${!isEmpty(this.delim) ? `${this.delim} ` : ''}${this.aggExprList + .map((aggTerm) => aggTerm.toString()) + .join(', ')}${!isEmpty(this.groupExprList) ? ` ${this.groupExprList.toString()}` : ''}${ + !isEmpty(this.dedupSplitValue) ? ` ${this.dedupSplitValue}` : '' + }`; + } +} diff --git a/dashboards-observability/common/query_manager/ast/types/index.ts b/dashboards-observability/common/query_manager/ast/types/index.ts new file mode 100644 index 000000000..956731baf --- /dev/null +++ b/dashboards-observability/common/query_manager/ast/types/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export { + ExpressionChunk, + SpanChunk, + StatsAggregationChunk, + StatsAggregationFunctionChunk, + GroupByChunk, + GroupField, + statsChunk, + SpanExpressionChunk, + AggregationConfigurations, + PreviouslyParsedStaleStats +} from './stats'; diff --git a/dashboards-observability/common/query_manager/ast/types/stats.ts b/dashboards-observability/common/query_manager/ast/types/stats.ts new file mode 100644 index 000000000..959ae7847 --- /dev/null +++ b/dashboards-observability/common/query_manager/ast/types/stats.ts @@ -0,0 +1,74 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * stats chunck types + */ +export interface StatsAggregationChunk { + function: StatsAggregationFunctionChunk; + function_alias: string; +} + +export interface StatsAggregationFunctionChunk { + name: string; + value_expression: string; + percentile_agg_function: string; +} + +export interface GroupField { + name: string; +} + +export interface SpanChunk { + alias: string; + span_expression: SpanExpressionChunk; +} + +export interface SpanExpressionChunk { + type: string; + field: string; + time_unit: string; + literal_value: string; +} + +export interface GroupByChunk { + group_fields: Array; + span: SpanChunk | null; +} + +export interface statsChunk { + aggregations: Array; + groupby: GroupByChunk; + partitions: ExpressionChunk; + all_num: ExpressionChunk; + delim: ExpressionChunk; + dedup_split_value: ExpressionChunk; +} + +export interface ExpressionChunk { + keyword: string; + sign: string; + value: string | number; +} + +export interface DataConfigMetric { + alias: string; + label: string; + name: string; + aggregation: string; +} + +export interface AggregationConfigurations { + metrics: Array; + dimensions: Array; + span: SpanChunk; +} + +export interface PreviouslyParsedStaleStats { + partitions: ExpressionChunk; + all_num: ExpressionChunk; + delim: ExpressionChunk; + dedup_split_value: ExpressionChunk; +} diff --git a/dashboards-observability/common/query_manager/index.ts b/dashboards-observability/common/query_manager/index.ts new file mode 100644 index 000000000..72b5cd2f6 --- /dev/null +++ b/dashboards-observability/common/query_manager/index.ts @@ -0,0 +1,6 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export { QueryManager } from './ppl_query_manager'; diff --git a/dashboards-observability/common/query_manager/ppl_query_manager.ts b/dashboards-observability/common/query_manager/ppl_query_manager.ts new file mode 100644 index 000000000..513485cf5 --- /dev/null +++ b/dashboards-observability/common/query_manager/ppl_query_manager.ts @@ -0,0 +1,17 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { PPLQueryBuilder } from './query_builder/ppl_query_builder'; +import { PPLQueryParser } from './query_parser/ppl_query_parser'; + +export class QueryManager { + queryBuilder(): PPLQueryBuilder { + return new PPLQueryBuilder(); + } + + queryParser(): PPLQueryParser { + return new PPLQueryParser(); + } +} diff --git a/dashboards-observability/common/query_manager/query_builder/index.ts b/dashboards-observability/common/query_manager/query_builder/index.ts new file mode 100644 index 000000000..24e0492f5 --- /dev/null +++ b/dashboards-observability/common/query_manager/query_builder/index.ts @@ -0,0 +1,6 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export { PPLQueryBuilder } from './ppl_query_builder'; diff --git a/dashboards-observability/common/query_manager/query_builder/ppl_query_builder.ts b/dashboards-observability/common/query_manager/query_builder/ppl_query_builder.ts new file mode 100644 index 000000000..50ea50b41 --- /dev/null +++ b/dashboards-observability/common/query_manager/query_builder/ppl_query_builder.ts @@ -0,0 +1,39 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { PPLSyntaxParser } from '../antlr/ppl_syntax_parser'; +import { StatsBuilder } from '../ast/builder/stats_builder'; +import { StatsAstBuilder } from '../ast/builder/stats_ast_builder'; + +export class PPLQueryBuilder { + parser: PPLSyntaxParser | null = null; + + build(query: string, pplTokens: any) { + this.parser = new PPLSyntaxParser().parse(query); + return this.buildStats(query, pplTokens); + } + + buildStats(query: string, statsTokens: any) { + const statsTree = new StatsAstBuilder().visitRoot(this.parser!.root()); + const newStatsAstTree = new StatsBuilder(statsTokens).build(); + if (typeof statsTree.getStartEndIndicesOfOriginQuery !== 'function') { + return query + ' | ' + newStatsAstTree.toString(); + } + + const indices = statsTree.getStartEndIndicesOfOriginQuery(); + + if (indices.start !== -1 && indices.end !== -1) { + return ( + query.substring(0, indices.start) + + newStatsAstTree.toString() + + query.substring(indices.end + 1, query.length) + ); + } else if (indices && newStatsAstTree) { + return query + ' | ' + newStatsAstTree.toString(); + } + + return ''; + } +} diff --git a/dashboards-observability/common/query_manager/query_parser/index.ts b/dashboards-observability/common/query_manager/query_parser/index.ts new file mode 100644 index 000000000..c4afe0e5d --- /dev/null +++ b/dashboards-observability/common/query_manager/query_parser/index.ts @@ -0,0 +1,6 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export { PPLQueryParser } from './ppl_query_parser'; diff --git a/dashboards-observability/common/query_manager/query_parser/ppl_query_parser.ts b/dashboards-observability/common/query_manager/query_parser/ppl_query_parser.ts new file mode 100644 index 000000000..9a39276e0 --- /dev/null +++ b/dashboards-observability/common/query_manager/query_parser/ppl_query_parser.ts @@ -0,0 +1,25 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { PPLSyntaxParser } from '../antlr/ppl_syntax_parser'; +import { OpenSearchPPLParser } from '../antlr/output/OpenSearchPPLParser'; +import { StatsAstBuilder } from '../ast/builder/stats_ast_builder'; + +export class PPLQueryParser { + parser: OpenSearchPPLParser | null = null; + visitor: any = null; + rawQuery: string = ''; + + parse(pplQuery: string) { + this.rawQuery = pplQuery; + this.parser = new PPLSyntaxParser().parse(this.rawQuery); + return this; + } + + getStats() { + this.visitor = new StatsAstBuilder(); + return this.visitor.visitRoot(this.parser!.root()).getTokens(); + } +} diff --git a/dashboards-observability/common/query_manager/utils/index.ts b/dashboards-observability/common/query_manager/utils/index.ts new file mode 100644 index 000000000..eded2c827 --- /dev/null +++ b/dashboards-observability/common/query_manager/utils/index.ts @@ -0,0 +1,42 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { AggregationConfigurations, PreviouslyParsedStaleStats } from '../ast/types'; + +export const composeAggregations = ( + aggConfig: AggregationConfigurations, + staleStats: PreviouslyParsedStaleStats +) => { + return { + aggregations: aggConfig.metrics.map((metric) => ({ + function_alias: metric.alias, + function: { + name: metric.aggregation, + value_expression: metric.name, + percentile_agg_function: '', + }, + })), + groupby: { + group_fields: aggConfig.dimensions.map((dimension) => ({ name: dimension.name })), + span: aggConfig.span ? composeSpan(aggConfig.span) : null, + }, + partitions: staleStats?.partitions ?? {}, + all_num: staleStats?.all_num ?? {}, + delim: staleStats?.delim ?? {}, + dedup_split_value: staleStats?.dedup_split_value ?? {}, + }; +}; + +const composeSpan = (spanConfig) => { + return { + alias: spanConfig.alias ?? '', + span_expression: { + type: spanConfig.time_field[0]?.type ?? 'timestamp', + field: spanConfig.time_field[0]?.name ?? 'timestamp', + time_unit: spanConfig.unit[0]?.value ?? 'd', + literal_value: spanConfig.interval ?? 1 + } + }; +}; diff --git a/dashboards-observability/common/types/app_analytics.ts b/dashboards-observability/common/types/application_analytics.ts similarity index 57% rename from dashboards-observability/common/types/app_analytics.ts rename to dashboards-observability/common/types/application_analytics.ts index c73bbb0b0..11f42c236 100644 --- a/dashboards-observability/common/types/app_analytics.ts +++ b/dashboards-observability/common/types/application_analytics.ts @@ -7,17 +7,20 @@ export interface OptionType { label: string; } -export interface ApplicationListType { - name: string; +export interface ApplicationType { id: string; - panelId: string; - composition: string[]; dateCreated: string; dateModified: string; - availability: { name: string; color: string; mainVisId: string }; + name: string; + description: string; + baseQuery: string; + servicesEntities: string[]; + traceGroups: string[]; + panelId: string; + availability: { name: string; color: string; availabilityVisId: string }; } -export interface ApplicationType { +export interface ApplicationRequestType { name: string; description: string; baseQuery: string; @@ -26,3 +29,9 @@ export interface ApplicationType { panelId: string; availabilityVisId: string; } + +export interface AvailabilityType { + name: string; + color: string; + availabilityVisId: string; +} diff --git a/dashboards-observability/common/types/explorer.ts b/dashboards-observability/common/types/explorer.ts index d43aba751..a734d7150 100644 --- a/dashboards-observability/common/types/explorer.ts +++ b/dashboards-observability/common/types/explorer.ts @@ -16,7 +16,7 @@ import { SELECTED_TIMESTAMP, SELECTED_DATE_RANGE, } from '../constants/explorer'; -import { CoreStart, HttpStart, NotificationsStart } from '../../../../src/core/public'; +import { CoreStart, HttpSetup, HttpStart, NotificationsStart } from '../../../../src/core/public'; import SavedObjects from '../../public/services/saved_objects/event_analytics/saved_objects'; import TimestampUtils from '../../public/services/timestamp/timestamp'; import PPLService from '../../public/services/requests/ppl'; @@ -31,6 +31,7 @@ export interface IQueryTab { export interface IField { name: string; type: string; + label?: string; } export interface ITabQueryResults { @@ -150,6 +151,31 @@ export interface SavedVizRes { tenant: string; } +export interface ExplorerDataType { + jsonData: object[]; + jsonDataAll: object[]; +} + +export interface Query { + finalQuery: string; + index: string; + isLoaded: boolean; + objectType: string; + rawQuery: string; + savedObjectId: string; + selectedDateRange: string[]; + selectedTimestamp: string; + tabCreatedType: string; +} + +export interface ExplorerData { + explorerData?: ExplorerDataType; + explorerFields?: IExplorerFields; + query?: Query; + http?: HttpSetup; + pplService?: PPLService; +} + export interface IVisualizationContainerPropsData { appData?: { fromApp: boolean }; rawVizData?: any; @@ -160,6 +186,7 @@ export interface IVisualizationContainerPropsData { xaxis: IField[]; yaxis: IField[]; }; + explorer?: ExplorerData; } export interface IVisualizationContainerPropsVis { @@ -186,9 +213,11 @@ export interface IConfigPanelOptions { export interface IConfigPanelOptionSection { name: string; component: null; - mapTo: 'mode'; + mapTo: string; props?: any; isSingleSelection?: boolean; + defaultState?: boolean | string; + eleType?: string; } export interface IVisualizationTypeDefination { @@ -196,13 +225,13 @@ export interface IVisualizationTypeDefination { type: string; id: string; label: string; - fullLabel: string; + fulllabel: string; category: string; icon: React.ReactNode; - editorConfig: { + editorconfig: { panelTabs: IConfigPanelTab; }; - visConfig: { + visconfig: { layout: Partial; config: Partial; }; @@ -227,3 +256,30 @@ export interface LiveTailProps { isLiveTailPopoverOpen: boolean; dataTestSubj: string; } + +export interface ConfigListEntry { + label: string; + aggregation: string; + custom_label: string; + name: string; + side: string; + type: string; +} + +export interface HistogramConfigList { + bucketSize: string; + bucketOffset: string; +} + +export interface DimensionSpan { + time_field: IField; + interval: number; + unit: string; +} + +export interface ConfigList { + dimensions?: ConfigListEntry[] | HistogramConfigList[]; + metrics?: ConfigListEntry[]; + breakdowns?: ConfigListEntry[] | HistogramConfigList[]; + span?: DimensionSpan; +} diff --git a/dashboards-observability/opensearch_dashboards.json b/dashboards-observability/opensearch_dashboards.json index 2b9ffd295..75b51d910 100644 --- a/dashboards-observability/opensearch_dashboards.json +++ b/dashboards-observability/opensearch_dashboards.json @@ -1,7 +1,7 @@ { "id": "observabilityDashboards", - "version": "2.0.0.0", - "opensearchDashboardsVersion": "2.0.0", + "version": "2.2.0.0", + "opensearchDashboardsVersion": "2.2.0", "server": true, "ui": true, "requiredPlugins": [ diff --git a/dashboards-observability/package.json b/dashboards-observability/package.json index 4e422d934..d5f1d540f 100644 --- a/dashboards-observability/package.json +++ b/dashboards-observability/package.json @@ -1,6 +1,6 @@ { "name": "observability-dashboards", - "version": "2.0.0.0", + "version": "2.2.0.0", "main": "index.ts", "license": "Apache-2.0", "scripts": { @@ -9,7 +9,8 @@ "test": "../../node_modules/.bin/jest --config ./test/jest.config.js", "cypress:run": "TZ=America/Los_Angeles cypress run", "cypress:open": "TZ=America/Los_Angeles cypress open", - "plugin_helpers": "node ../../scripts/plugin_helpers" + "plugin_helpers": "node ../../scripts/plugin_helpers", + "postinstall": "antlr4ts -visitor ./common/query_manager/antlr/grammar/OpenSearchPPLLexer.g4 -Xexact-output-dir -o ./common/query_manager/antlr/output && antlr4ts -visitor ./common/query_manager/antlr/grammar/OpenSearchPPLParser.g4 -Xexact-output-dir -o ./common/query_manager/antlr/output" }, "dependencies": { "@algolia/autocomplete-core": "^1.4.1", @@ -17,8 +18,14 @@ "@nteract/outputs": "^3.0.11", "@nteract/presentational-components": "^3.4.3", "@reduxjs/toolkit": "^1.6.1", + "ag-grid-community": "^27.3.0", + "ag-grid-react": "^27.3.0", + "antlr4": "4.8.0", + "antlr4ts": "^0.5.0-alpha.4", "plotly.js-dist": "^2.2.0", + "postinstall": "^0.7.4", "react-graph-vis": "^1.0.5", + "react-paginate": "^8.1.3", "react-plotly.js": "^2.5.1" }, "devDependencies": { @@ -26,6 +33,7 @@ "@types/enzyme-adapter-react-16": "^1.0.6", "@types/react-plotly.js": "^2.5.0", "@types/react-test-renderer": "^16.9.1", + "antlr4ts-cli": "^0.5.0-alpha.4", "cypress": "^5.0.0", "eslint": "^6.8.0", "jest-dom": "^4.0.0", diff --git a/dashboards-observability/public/.DS_Store b/dashboards-observability/public/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..dbd07c1a1c1d289c1b490405a326e8a55ae29325 GIT binary patch literal 6148 zcmeHKJ8r^25S>XVP-t9I?iIMf%5qNN3m_#C4KXMr)UI+aj>emhq98+&f+l(+&Ai>& zd29I<9*>A<`}MjKX+&fWH%Fk~B9M^^Pys6Nqkw%M3f!hP6`=yd49* i9b;qdc*nm7hJ9eJk%`7>a;(5S$@6*vQa;1$mR literal 0 HcmV?d00001 diff --git a/dashboards-observability/public/components/application_analytics/components/app_table.tsx b/dashboards-observability/public/components/application_analytics/components/app_table.tsx index 27611aa76..75fe228af 100644 --- a/dashboards-observability/public/components/application_analytics/components/app_table.tsx +++ b/dashboards-observability/public/components/application_analytics/components/app_table.tsx @@ -34,16 +34,15 @@ import { import _ from 'lodash'; import React, { ReactElement, useEffect, useState } from 'react'; import moment from 'moment'; +import { DeleteModal } from '../../common/helpers/delete_modal'; import { AppAnalyticsComponentDeps } from '../home'; import { getCustomModal } from '../../custom_panels/helpers/modal_containers'; -import { getClearModal } from '../helpers/modal_containers'; import { pageStyles, UI_DATE_FORMAT } from '../../../../common/constants/shared'; -import { ApplicationListType } from '../../../../common/types/app_analytics'; -import { AvailabilityType } from '../helpers/types'; +import { ApplicationType, AvailabilityType } from '../../../../common/types/application_analytics'; interface AppTableProps extends AppAnalyticsComponentDeps { loading: boolean; - applications: ApplicationListType[]; + applications: ApplicationType[]; fetchApplications: () => void; renameApplication: (newAppName: string, appId: string) => void; deleteApplication: (appList: string[], panelIdList: string[], toastMessage?: string) => void; @@ -66,7 +65,7 @@ export function AppTable(props: AppTableProps) { const [isModalVisible, setIsModalVisible] = useState(false); const [isActionsPopoverOpen, setIsActionsPopoverOpen] = useState(false); const [modalLayout, setModalLayout] = useState(); - const [selectedApplications, setSelectedApplications] = useState([]); + const [selectedApplications, setSelectedApplications] = useState([]); const createButtonText = 'Create application'; useEffect(() => { @@ -129,12 +128,12 @@ export function AppTable(props: AppTableProps) { const deleteApp = () => { const applicationString = `application${selectedApplications.length > 1 ? 's' : ''}`; setModalLayout( - getClearModal( - closeModal, - onDelete, - `Delete ${selectedApplications.length} ${applicationString}`, - `Are you sure you want to delete the selected ${selectedApplications.length} ${applicationString}?` - ) + ); showModal(); }; @@ -182,7 +181,7 @@ export function AppTable(props: AppTableProps) { // Add sample application, ]; - const renderAvailability = (value: AvailabilityType, record: ApplicationListType) => { + const renderAvailability = (value: AvailabilityType, record: ApplicationType) => { if (value.color === 'loading') { return ; } else if (value.name) { @@ -230,10 +229,10 @@ export function AppTable(props: AppTableProps) { name: 'Composition', sortable: false, truncateText: true, - render: (value) => ( - + render: (value, record) => ( + - {value.join(', ')} + {record.servicesEntities.concat(record.traceGroups).join(', ')} ), @@ -250,7 +249,7 @@ export function AppTable(props: AppTableProps) { sortable: true, render: (value) => {moment(value).format(UI_DATE_FORMAT)}, }, - ] as Array>; + ] as Array>; return (
diff --git a/dashboards-observability/public/components/application_analytics/components/application.tsx b/dashboards-observability/public/components/application_analytics/components/application.tsx index fb55a6ced..ba5132be7 100644 --- a/dashboards-observability/public/components/application_analytics/components/application.tsx +++ b/dashboards-observability/public/components/application_analytics/components/application.tsx @@ -57,7 +57,10 @@ import { IQueryTab } from '../../../../common/types/explorer'; import { NotificationsStart } from '../../../../../../src/core/public'; import { AppAnalyticsComponentDeps } from '../home'; import { CustomPanelView } from '../../../../public/components/custom_panels/custom_panel_view'; -import { ApplicationType } from '../../../../common/types/app_analytics'; +import { + ApplicationRequestType, + ApplicationType, +} from '../../../../common/types/application_analytics'; import { CUSTOM_PANELS_API_PREFIX } from '../../../../common/constants/custom_panels'; import { ServiceDetailFlyout } from './flyout_components/service_detail_flyout'; import { SpanDetailFlyout } from '../../../../public/components/trace_analytics/components/traces/span_detail_flyout'; @@ -83,7 +86,7 @@ interface AppDetailProps extends AppAnalyticsComponentDeps { savedObjects: SavedObjects; timestampUtils: TimestampUtils; notifications: NotificationsStart; - updateApp: (appId: string, updateAppData: Partial, type: string) => void; + updateApp: (appId: string, updateAppData: Partial, type: string) => void; setToasts: (title: string, color?: string, text?: ReactChild) => void; callback: (childfunction: () => void) => void; } @@ -109,13 +112,16 @@ export function Application(props: AppDetailProps) { callback, } = props; const [application, setApplication] = useState({ + id: '', + dateCreated: '', + dateModified: '', name: '', description: '', baseQuery: '', servicesEntities: [], traceGroups: [], panelId: '', - availabilityVisId: '', + availability: { name: '', color: '', availabilityVisId: '' }, }); const dispatch = useDispatch(); const [triggerAvailability, setTriggerAvailability] = useState(false); @@ -381,7 +387,11 @@ export function Application(props: AppDetailProps) { }; const updateAvailabilityVizId = (vizs: VisualizationType[]) => { - if (!vizs.map((viz) => viz.savedVisualizationId).includes(application.availabilityVisId)) { + if ( + !vizs + .map((viz) => viz.savedVisualizationId) + .includes(application.availability.availabilityVisId) + ) { updateApp(appId, { availabilityVisId: '' }, 'editAvailability'); } }; diff --git a/dashboards-observability/public/components/application_analytics/components/config_components/service_config.tsx b/dashboards-observability/public/components/application_analytics/components/config_components/service_config.tsx index 569cb8609..30b78adcd 100644 --- a/dashboards-observability/public/components/application_analytics/components/config_components/service_config.tsx +++ b/dashboards-observability/public/components/application_analytics/components/config_components/service_config.tsx @@ -22,7 +22,7 @@ import { ServiceObject } from '../../../trace_analytics/components/common/plots/ import { ServiceMap } from '../../../trace_analytics/components/services'; import { handleServiceMapRequest } from '../../../trace_analytics/requests/services_request_handler'; import { AppAnalyticsComponentDeps } from '../../home'; -import { OptionType } from '../../../../../common/types/app_analytics'; +import { OptionType } from '../../../../../common/types/application_analytics'; import { getClearModal } from '../../helpers/modal_containers'; interface ServiceConfigProps extends AppAnalyticsComponentDeps { diff --git a/dashboards-observability/public/components/application_analytics/components/config_components/trace_config.tsx b/dashboards-observability/public/components/application_analytics/components/config_components/trace_config.tsx index e7bcf1167..e0ff9a1bb 100644 --- a/dashboards-observability/public/components/application_analytics/components/config_components/trace_config.tsx +++ b/dashboards-observability/public/components/application_analytics/components/config_components/trace_config.tsx @@ -18,7 +18,7 @@ import { import DSLService from 'public/services/requests/dsl'; import React, { useEffect, useState } from 'react'; import { FilterType } from 'public/components/trace_analytics/components/common/filters/filters'; -import { OptionType } from '../../../../../common/types/app_analytics'; +import { OptionType } from '../../../../../common/types/application_analytics'; import { filtersToDsl } from '../../../trace_analytics/components/common/helper_functions'; import { handleDashboardRequest } from '../../../trace_analytics/requests/dashboard_request_handler'; import { AppAnalyticsComponentDeps } from '../../home'; diff --git a/dashboards-observability/public/components/application_analytics/components/configuration.tsx b/dashboards-observability/public/components/application_analytics/components/configuration.tsx index c8c4ce2cb..8cb8080ff 100644 --- a/dashboards-observability/public/components/application_analytics/components/configuration.tsx +++ b/dashboards-observability/public/components/application_analytics/components/configuration.tsx @@ -2,7 +2,6 @@ * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 */ -/* eslint-disable react-hooks/exhaustive-deps */ import { EuiBreadcrumb, @@ -24,7 +23,7 @@ import { EuiText, EuiTitle, } from '@elastic/eui'; -import { ApplicationType } from 'common/types/app_analytics'; +import { ApplicationRequestType, ApplicationType } from 'common/types/application_analytics'; import { last } from 'lodash'; import React, { useState } from 'react'; @@ -34,7 +33,7 @@ interface ConfigProps { parentBreadcrumbs: EuiBreadcrumb[]; visWithAvailability: EuiSelectOption[]; switchToAvailability: () => void; - updateApp: (appId: string, updateAppData: Partial, type: string) => void; + updateApp: (appId: string, updateAppData: Partial, type: string) => void; } export const Configuration = (props: ConfigProps) => { @@ -46,7 +45,9 @@ export const Configuration = (props: ConfigProps) => { updateApp, switchToAvailability, } = props; - const [availabilityVisId, setAvailabilityVisId] = useState(application.availabilityVisId || ''); + const [availabilityVisId, setAvailabilityVisId] = useState( + application.availability.availabilityVisId || '' + ); const onAvailabilityVisChange = (event: any) => { setAvailabilityVisId(event.target.value); diff --git a/dashboards-observability/public/components/application_analytics/components/create.tsx b/dashboards-observability/public/components/application_analytics/components/create.tsx index 390aa3612..084d53b17 100644 --- a/dashboards-observability/public/components/application_analytics/components/create.tsx +++ b/dashboards-observability/public/components/application_analytics/components/create.tsx @@ -32,15 +32,19 @@ import { TraceConfig } from './config_components/trace_config'; import { ServiceConfig } from './config_components/service_config'; import { LogConfig } from './config_components/log_config'; import { PPLReferenceFlyout } from '../../../components/common/helpers'; -import { ApplicationType, OptionType } from '../../../../common/types/app_analytics'; +import { + ApplicationRequestType, + ApplicationType, + OptionType, +} from '../../../../common/types/application_analytics'; import { fetchAppById } from '../helpers/utils'; interface CreateAppProps extends AppAnalyticsComponentDeps { dslService: DSLService; pplService: PPLService; setToasts: (title: string, color?: string, text?: ReactChild) => void; - createApp: (app: ApplicationType, type: string) => void; - updateApp: (appId: string, updateAppData: Partial, type: string) => void; + createApp: (app: ApplicationRequestType, type: string) => void; + updateApp: (appId: string, updateAppData: Partial, type: string) => void; clearStorage: () => void; existingAppId: string; } @@ -70,13 +74,16 @@ export const CreateApp = (props: CreateAppProps) => { const editMode = existingAppId !== 'undefined'; const [existingApp, setExistingApp] = useState({ + id: existingAppId, + dateCreated: '', + dateModified: '', name: '', description: '', baseQuery: '', servicesEntities: [], traceGroups: [], panelId: '', - availabilityVisId: '', + availability: { name: '', color: '', availabilityVisId: '' }, }); useEffect(() => { diff --git a/dashboards-observability/public/components/application_analytics/components/flyout_components/availability_info_flyout.tsx b/dashboards-observability/public/components/application_analytics/components/flyout_components/availability_info_flyout.tsx new file mode 100644 index 000000000..86e668f41 --- /dev/null +++ b/dashboards-observability/public/components/application_analytics/components/flyout_components/availability_info_flyout.tsx @@ -0,0 +1,62 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + EuiFlyout, + EuiFlyoutHeader, + EuiTitle, + EuiFlyoutBody, + EuiText, + EuiCodeBlock, + EuiFlyoutFooter, + EuiButton, +} from '@elastic/eui'; +import React from 'react'; + +interface AvailabilityInfoFlyoutProps { + closeFlyout: () => void; +} + +export function AvailabilityInfoFlyout(props: AvailabilityInfoFlyoutProps) { + const { closeFlyout } = props; + + return ( + + + +

Availability

+
+
+ + +

Configure availability

+ Availability is the status of your application determined by availability levels set on a + time series metric. To create an availability level, you must configure the following: +
    +
  • color: The color of the availability badge on the home page
  • +
  • name: The text in the availability badge on the home page
  • +
  • expression: Comparison operator to determine the availability
  • +
  • value: Value to use when calculating availability
  • +
+

Configuring availability

+ By default, Application analytics shows results from the last 24 hours of your data. To + see data from a different timeframe, use the date and time selector. +

Time series metric

A time series metric is any visualization that has a query that + spans over a timestamp and is a bar/line chart. You can use the PPL language to define + arbitrary conditions on your logs to create a visualization over time. +

Example

+ + {'source = | ... | ... | stats ... by span(, 1h)'} + + You can then choose Bar or Line in visualization + configurations to create a time series metric. +
+
+ + Close + +
+ ); +} diff --git a/dashboards-observability/public/components/application_analytics/helpers/types.tsx b/dashboards-observability/public/components/application_analytics/helpers/types.tsx deleted file mode 100644 index 07ac03c9d..000000000 --- a/dashboards-observability/public/components/application_analytics/helpers/types.tsx +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export interface AvailabilityType { - name: string; - color: string; - mainVisId: string; -} diff --git a/dashboards-observability/public/components/application_analytics/helpers/utils.tsx b/dashboards-observability/public/components/application_analytics/helpers/utils.tsx index d956fb06b..f212a3caf 100644 --- a/dashboards-observability/public/components/application_analytics/helpers/utils.tsx +++ b/dashboards-observability/public/components/application_analytics/helpers/utils.tsx @@ -5,7 +5,7 @@ /* eslint-disable no-console */ import { EuiDescriptionList, EuiSelectOption, EuiSpacer, EuiText } from '@elastic/eui'; -import { ApplicationListType, ApplicationType } from 'common/types/app_analytics'; +import { ApplicationType, AvailabilityType } from 'common/types/application_analytics'; import { FilterType } from 'public/components/trace_analytics/components/common/filters/filters'; import React, { Dispatch, ReactChild } from 'react'; import { batch } from 'react-redux'; @@ -36,7 +36,6 @@ import { remove as removeQueryResult, } from '../../event_analytics/redux/slices/query_result_slice'; import { addTab, removeTab } from '../../event_analytics/redux/slices/query_tab_slice'; -import { AvailabilityType } from './types'; // Name validation export const isNameValid = (name: string, existingNames: string[]) => { @@ -100,18 +99,18 @@ export const fetchAppById = async ( ) => { return http .get(`${APP_ANALYTICS_API_PREFIX}/${applicationId}`) - .then(async (res) => { - res.application.availabilityVisId = ( + .then(async (res: ApplicationType) => { + res.availability.availabilityVisId = ( await calculateAvailability( http, pplService, - res.application, - res.application.availabilityVisId, + res, + res.availability.availabilityVisId, setVisWithAvailability ) - ).mainVisId; - setApplication(res.application); - const serviceFilters = res.application.servicesEntities.map((ser: string) => { + ).availabilityVisId; + setApplication(res); + const serviceFilters = res.servicesEntities.map((ser: string) => { return { field: 'serviceName', operator: 'is', @@ -120,7 +119,7 @@ export const fetchAppById = async ( disabled: false, }; }); - const traceFilters = res.application.traceGroups.map((tra: string) => { + const traceFilters = res.traceGroups.map((tra: string) => { return { field: 'traceGroup', operator: 'is', @@ -194,11 +193,11 @@ export const fetchPanelsVizIdList = async (http: HttpSetup, appPanelId: string) export const calculateAvailability = async ( http: HttpSetup, pplService: PPLService, - application: ApplicationType | ApplicationListType, + application: ApplicationType, availabilityVisId: string, setVisWithAvailability: (visList: EuiSelectOption[]) => void ): Promise => { - let availability = { name: '', color: '', mainVisId: '' }; + let availability = { name: '', color: '', availabilityVisId: '' }; const panelId = application.panelId; if (!panelId) return availability; // Fetches saved visualizations associated to application's panel @@ -252,7 +251,7 @@ export const calculateAvailability = async ( availability = { name: '', color: 'null', - mainVisId: '', + availabilityVisId: '', }; } else { if (!availabilityFound) { @@ -263,7 +262,7 @@ export const calculateAvailability = async ( availability = { name: level.name, color: level.color, - mainVisId: visualizationId, + availabilityVisId: visualizationId, }; availabilityFound = true; } @@ -273,7 +272,7 @@ export const calculateAvailability = async ( availability = { name: level.name, color: level.color, - mainVisId: visualizationId, + availabilityVisId: visualizationId, }; availabilityFound = true; } @@ -283,7 +282,7 @@ export const calculateAvailability = async ( availability = { name: level.name, color: level.color, - mainVisId: visualizationId, + availabilityVisId: visualizationId, }; availabilityFound = true; } @@ -293,7 +292,7 @@ export const calculateAvailability = async ( availability = { name: level.name, color: level.color, - mainVisId: visualizationId, + availabilityVisId: visualizationId, }; availabilityFound = true; } @@ -303,7 +302,7 @@ export const calculateAvailability = async ( availability = { name: level.name, color: level.color, - mainVisId: visualizationId, + availabilityVisId: visualizationId, }; availabilityFound = true; } @@ -313,7 +312,7 @@ export const calculateAvailability = async ( availability = { name: level.name, color: level.color, - mainVisId: visualizationId, + availabilityVisId: visualizationId, }; availabilityFound = true; } @@ -328,7 +327,7 @@ export const calculateAvailability = async ( } setVisWithAvailability(visWithAvailability); if (!availabilityFound && visWithAvailability.length > 0) { - return { name: '', color: 'undefined', mainVisId: '' }; + return { name: '', color: 'undefined', availabilityVisId: '' }; } return availability; }; diff --git a/dashboards-observability/public/components/application_analytics/home.tsx b/dashboards-observability/public/components/application_analytics/home.tsx index 1d837d437..95ab3d978 100644 --- a/dashboards-observability/public/components/application_analytics/home.tsx +++ b/dashboards-observability/public/components/application_analytics/home.tsx @@ -24,7 +24,10 @@ import { handleIndicesExistRequest } from '../trace_analytics/requests/request_h import { ObservabilitySideBar } from '../common/side_nav'; import { NotificationsStart } from '../../../../../src/core/public'; import { APP_ANALYTICS_API_PREFIX } from '../../../common/constants/application_analytics'; -import { ApplicationListType, ApplicationType } from '../../../common/types/app_analytics'; +import { + ApplicationRequestType, + ApplicationType, +} from '../../../common/types/application_analytics'; import { calculateAvailability, fetchPanelsVizIdList, @@ -69,7 +72,7 @@ export const Home = (props: HomeProps) => { } = props; const [triggerSwitchToEvent, setTriggerSwitchToEvent] = useState(0); const dispatch = useDispatch(); - const [applicationList, setApplicationList] = useState([]); + const [applicationList, setApplicationList] = useState([]); const [toasts, setToasts] = useState([]); const [indicesExist, setIndicesExist] = useState(true); const [appConfigs, setAppConfigs] = useState([]); @@ -208,10 +211,10 @@ export const Home = (props: HomeProps) => { .get(`${APP_ANALYTICS_API_PREFIX}/`) .then(async (res) => { // Want to calculate availability going down the table - const mainVisIdStore: Record = {}; + const availabilityVisIdStore: Record = {}; for (let i = 0; i < res.data.length; i++) { - mainVisIdStore[res.data[i].id] = res.data[i].availability.mainVisId; - res.data[i].availability = { name: '', color: 'loading', mainVisId: '' }; + availabilityVisIdStore[res.data[i].id] = res.data[i].availability.availabilityVisId; + res.data[i].availability = { name: '', color: 'loading', availabilityVisId: '' }; } setApplicationList(res.data); for (let i = res.data.length - 1; i > -1; i--) { @@ -219,12 +222,12 @@ export const Home = (props: HomeProps) => { http, pplService, res.data[i], - mainVisIdStore[res.data[i].id], + availabilityVisIdStore[res.data[i].id], () => {} ); // Need to set state with new object to trigger re-render setApplicationList([ - ...res.data.filter((app: ApplicationListType) => app.id !== res.data[i].id), + ...res.data.filter((app: ApplicationType) => app.id !== res.data[i].id), res.data[i], ]); } @@ -236,7 +239,7 @@ export const Home = (props: HomeProps) => { }; // Create a new application - const createApp = (application: ApplicationType, type: string) => { + const createApp = (application: ApplicationRequestType, type: string) => { const toast = isNameValid( application.name, applicationList.map((obj) => obj.name) @@ -248,7 +251,7 @@ export const Home = (props: HomeProps) => { const requestBody = { name: application.name, - description: application.description, + description: application.description || '', baseQuery: application.baseQuery, servicesEntities: application.servicesEntities, traceGroups: application.traceGroups, @@ -308,7 +311,11 @@ export const Home = (props: HomeProps) => { }; // Update existing application - const updateApp = (appId: string, updateAppData: Partial, type: string) => { + const updateApp = ( + appId: string, + updateAppData: Partial, + type: string + ) => { const requestBody = { appId, updateBody: updateAppData, diff --git a/dashboards-observability/public/components/common/helpers/delete_modal.tsx b/dashboards-observability/public/components/common/helpers/delete_modal.tsx new file mode 100644 index 000000000..9bf80ec1f --- /dev/null +++ b/dashboards-observability/public/components/common/helpers/delete_modal.tsx @@ -0,0 +1,79 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React, { useState } from 'react'; +import { + EuiOverlayMask, + EuiModal, + EuiButton, + EuiButtonEmpty, + EuiFieldText, + EuiForm, + EuiFormRow, + EuiModalBody, + EuiModalFooter, + EuiModalHeader, + EuiModalHeaderTitle, + EuiSpacer, + EuiText, +} from '@elastic/eui'; + +export const DeleteModal = ({ + onCancel, + onConfirm, + title, + message, +}: { + onCancel: ( + event?: React.KeyboardEvent | React.MouseEvent + ) => void; + onConfirm: (event?: React.MouseEvent) => void; + title: string; + message: string; +}) => { + const [value, setValue] = useState(''); + const onChange = (e: React.ChangeEvent) => { + setValue(e.target.value); + }; + return ( + + + + {title} + + + + {message} + The action cannot be undone. + + + + onChange(e)} + data-test-subj="popoverModal__deleteTextInput" + /> + + + + + + Cancel + onConfirm()} + color="danger" + fill + disabled={value !== 'delete'} + data-test-subj="popoverModal__deleteButton" + > + Delete + + + + + ); +}; diff --git a/dashboards-observability/public/components/common/search/autocomplete.tsx b/dashboards-observability/public/components/common/search/autocomplete.tsx index 3d3fdac26..a8c4007a7 100644 --- a/dashboards-observability/public/components/common/search/autocomplete.tsx +++ b/dashboards-observability/public/components/common/search/autocomplete.tsx @@ -185,7 +185,13 @@ export const Autocomplete = (props: AutocompleteProps) => {
-
+ + {fullWord.slice(0, -item.suggestion.length)} + {item.suggestion} + +
+ {/*
{ }
`, }} - /> + /> */}
diff --git a/dashboards-observability/public/components/common/search/search.tsx b/dashboards-observability/public/components/common/search/search.tsx index b4e2ebb16..ed9f85381 100644 --- a/dashboards-observability/public/components/common/search/search.tsx +++ b/dashboards-observability/public/components/common/search/search.tsx @@ -16,8 +16,8 @@ import { EuiBadge, EuiContextMenuPanel, EuiToolTip, + EuiCallOut } from '@elastic/eui'; -import _ from 'lodash'; import { DatePicker } from './date_picker'; import '@algolia/autocomplete-theme-classic'; import { Autocomplete } from './autocomplete'; @@ -82,10 +82,10 @@ export const Search = (props: any) => { stopLive, setIsLiveTailPopoverOpen, liveTailName, + searchError = null, } = props; - + const appLogEvents = tabId.match(APP_ANALYTICS_TAB_ID_REGEX); - const [isSavePanelOpen, setIsSavePanelOpen] = useState(false); const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); @@ -247,6 +247,17 @@ export const Search = (props: any) => { )} + { searchError && searchError.error && ( + + + +

+ {JSON.parse(searchError.message).error.details} +

+
+
+
) + } {flyout}
); diff --git a/dashboards-observability/public/components/custom_panels/custom_panel_table.tsx b/dashboards-observability/public/components/custom_panels/custom_panel_table.tsx index 305445285..a2c7ce8d6 100644 --- a/dashboards-observability/public/components/custom_panels/custom_panel_table.tsx +++ b/dashboards-observability/public/components/custom_panels/custom_panel_table.tsx @@ -38,10 +38,11 @@ import { CUSTOM_PANELS_DOCUMENTATION_URL, } from '../../../common/constants/custom_panels'; import { UI_DATE_FORMAT } from '../../../common/constants/shared'; -import { getCustomModal, DeletePanelModal } from './helpers/modal_containers'; +import { getCustomModal } from './helpers/modal_containers'; import { CustomPanelListType } from '../../../common/types/custom_panels'; import { getSampleDataModal } from '../common/helpers/add_sample_modal'; import { pageStyles } from '../../../common/constants/shared'; +import { DeleteModal } from '../common/helpers/delete_modal'; /* * "CustomPanelTable" module, used to view all the saved panels @@ -177,7 +178,7 @@ export const CustomPanelTable = ({ const deletePanel = () => { const customPanelString = `operational panel${selectedCustomPanels.length > 1 ? 's' : ''}`; setModalLayout( - { const deletePanel = () => { setModalLayout( - - - +
- - + className="euiText euiText--extraSmall lnsChart__empty" + data-test-subj="vizWorkspace__noData" + > + +
+ +
+ + + + + + +
+ +

+ + + No results found + + +

+
+ +
+ +
+ + @@ -853,15 +1567,85 @@ exports[`Utils helper functions renders displayVisualization function 2`] = ` "defaultAxes": Object { "xaxis": Array [ Object { + "aggregation": "", + "custom_label": "", + "label": "", + "name": "", + "side": "right", + "type": "", + }, + ], + "yaxis": Array [ + Object { + "label": "avg(FlightDelayMin)", + "name": "avg(FlightDelayMin)", + "type": "double", + }, + Object { + "label": "Carrier", "name": "Carrier", "type": "keyword", }, ], - "yaxis": Array [ + }, + "explorer": Object { + "explorerData": Object { + "data": Object { + "Carrier": Array [ + "BeatsWest", + "Logstash Airways", + "OpenSearch Dashboards Airlines", + "OpenSearch-Air", + ], + "avg(FlightDelayMin)": Array [ + 53.65384615384615, + 45.36144578313253, + 63.1578947368421, + 46.81318681318681, + ], + }, + "jsonData": Array [ + Object { + "Carrier": "BeatsWest", + "avg(FlightDelayMin)": 53.65384615384615, + }, + Object { + "Carrier": "Logstash Airways", + "avg(FlightDelayMin)": 45.36144578313253, + }, + Object { + "Carrier": "OpenSearch Dashboards Airlines", + "avg(FlightDelayMin)": 63.1578947368421, + }, + Object { + "Carrier": "OpenSearch-Air", + "avg(FlightDelayMin)": 46.81318681318681, + }, + ], + "metadata": Object { + "fields": Array [ + Object { + "name": "avg(FlightDelayMin)", + "type": "double", + }, + Object { + "name": "Carrier", + "type": "keyword", + }, + ], + }, + "size": 4, + "status": 200, + }, + "explorerFields": Array [ Object { "name": "avg(FlightDelayMin)", "type": "double", }, + Object { + "name": "Carrier", + "type": "keyword", + }, ], }, "indexFields": Object {}, @@ -914,76 +1698,312 @@ exports[`Utils helper functions renders displayVisualization function 2`] = ` "size": 4, "status": 200, }, - "userConfigs": Object {}, + "userConfigs": Object { + "dataConfig": Object { + "valueOptions": Object { + "dimensions": Array [ + Object { + "aggregation": "", + "custom_label": "", + "label": "", + "name": "", + "side": "right", + "type": "", + }, + ], + "metrics": Array [ + Object { + "label": "avg(FlightDelayMin)", + "name": "avg(FlightDelayMin)", + "type": "double", + }, + Object { + "label": "Carrier", + "name": "Carrier", + "type": "keyword", + }, + ], + }, + }, + }, }, "vis": Object { "category": "Visualizations", - "categoryAxis": "xaxis", + "categoryaxis": "xaxis", "component": [Function], - "editorConfig": Object { + "editorconfig": Object { "panelTabs": Array [ Object { "editor": [Function], "id": "data-panel", "mapTo": "dataConfig", - "name": "Data", + "name": "Style", "sections": Array [ Object { "editor": [Function], - "id": "value_options", - "mapTo": "valueOptions", - "name": "Value options", + "id": "legend", + "mapTo": "legend", + "name": "Legend", "schemas": Array [ Object { "component": null, - "isSingleSelection": true, - "mapTo": "xaxis", - "name": "X-axis", + "mapTo": "showLegend", + "name": "Show legend", + "props": Object { + "defaultSelections": Array [ + Object { + "id": "show", + "name": "Show", + }, + ], + "options": Array [ + Object { + "id": "show", + "name": "Show", + }, + Object { + "id": "hidden", + "name": "Hidden", + }, + ], + }, }, Object { "component": null, - "isSingleSelection": false, - "mapTo": "yaxis", - "name": "Y-axis", + "mapTo": "position", + "name": "Position", + "props": Object { + "defaultSelections": Array [ + Object { + "id": "v", + "name": "Right", + }, + ], + "options": Array [ + Object { + "id": "v", + "name": "Right", + }, + Object { + "id": "h", + "name": "Bottom", + }, + ], + }, + }, + Object { + "component": [Function], + "eleType": "input", + "mapTo": "legendSize", + "name": "Legend size", + "title": "Legend size", }, ], }, Object { "editor": [Function], - "id": "chart_options", - "mapTo": "chartOptions", - "name": "Chart options", + "id": "tooltip_options", + "mapTo": "tooltipOptions", + "name": "Tooltip options", "schemas": Array [ Object { "component": null, - "isSingleSelection": true, - "mapTo": "mode", + "mapTo": "tooltipMode", + "name": "Tooltip mode", + "props": Object { + "defaultSelections": Array [ + Object { + "id": "show", + "name": "Show", + }, + ], + "options": Array [ + Object { + "id": "show", + "name": "Show", + }, + Object { + "id": "hidden", + "name": "Hidden", + }, + ], + }, + }, + Object { + "component": null, + "mapTo": "tooltipText", + "name": "Tooltip text", + "props": Object { + "defaultSelections": Array [ + Object { + "id": "all", + "name": "All", + }, + ], + "options": Array [ + Object { + "id": "all", + "name": "All", + }, + Object { + "id": "x", + "name": "Dimension", + }, + Object { + "id": "y", + "name": "Metrics", + }, + ], + }, + }, + ], + }, + Object { + "editor": [Function], + "id": "chart_styles", + "mapTo": "chartStyles", + "name": "Chart styles", + "schemas": Array [ + Object { + "component": [Function], + "eleType": "buttons", + "mapTo": "style", "name": "Mode", "props": Object { "defaultSelections": Array [ Object { - "modeId": "lines", + "id": "lines", "name": "Lines", }, ], - "dropdownList": Array [ + "options": Array [ Object { - "modeId": "markers", - "name": "Markers", + "id": "lines", + "name": "Lines", }, Object { - "modeId": "lines", - "name": "Lines", + "id": "markers", + "name": "Marker", }, Object { - "modeId": "lines+markers", + "id": "lines+markers", "name": "Lines + Markers", }, ], }, }, + Object { + "component": [Function], + "eleType": "buttons", + "mapTo": "interpolation", + "name": "Interpolation", + "props": Object { + "defaultSelections": Array [ + Object { + "id": "spline", + "name": "Smooth", + }, + ], + "options": Array [ + Object { + "id": "linear", + "name": "Linear", + }, + Object { + "id": "spline", + "name": "Smooth", + }, + Object { + "id": "hv", + "name": "Step before", + }, + Object { + "id": "vh", + "name": "Step after", + }, + ], + }, + }, + Object { + "component": [Function], + "defaultState": 2, + "eleType": "slider", + "mapTo": "lineWidth", + "name": "Line width", + "props": Object { + "max": 10, + }, + }, + Object { + "component": [Function], + "defaultState": 40, + "eleType": "slider", + "mapTo": "fillOpacity", + "name": "Fill opacity", + "props": Object { + "max": 100, + }, + }, + Object { + "component": [Function], + "defaultState": 5, + "eleType": "slider", + "mapTo": "pointSize", + "name": "Point size", + "props": Object { + "max": 40, + }, + }, + Object { + "component": [Function], + "eleType": "input", + "mapTo": "labelSize", + "name": "Label size", + "title": "Label size", + }, + Object { + "component": [Function], + "defaultState": 0, + "eleType": "slider", + "mapTo": "rotateLabels", + "name": "Rotate labels", + "props": Object { + "max": 90, + "min": -90, + "showTicks": true, + "ticks": Array [ + Object { + "label": "-90°", + "value": -90, + }, + Object { + "label": "-45°", + "value": -45, + }, + Object { + "label": "0°", + "value": 0, + }, + Object { + "label": "45°", + "value": 45, + }, + Object { + "label": "90°", + "value": 90, + }, + ], + }, + }, ], }, + Object { + "editor": [Function], + "id": "color-theme", + "mapTo": "colorTheme", + "name": "Color theme", + "schemas": Array [], + }, Object { "defaultState": Array [], "editor": [Function], @@ -1009,18 +2029,18 @@ exports[`Utils helper functions renders displayVisualization function 2`] = ` }, ], }, - "fullLabel": "Line", + "fulllabel": "Time series", "icon": [Function], - "iconType": "visLine", + "icontype": "visLine", "id": "line", - "label": "Line", + "label": "Time series", "name": "line", "selection": Object { "dataLoss": "nothing", }, - "seriesAxis": "yaxis", + "seriesaxis": "yaxis", "type": "line", - "visConfig": Object { + "visconfig": Object { "config": Object { "barmode": "line", "displaylogo": false, @@ -1045,7 +2065,7 @@ exports[`Utils helper functions renders displayVisualization function 2`] = ` "#BD6F26", "#4C636F", ], - "height": 500, + "height": 1180, "legend": Object { "orientation": "v", "traceorder": "normal", @@ -1084,15 +2104,85 @@ exports[`Utils helper functions renders displayVisualization function 2`] = ` "defaultAxes": Object { "xaxis": Array [ Object { + "aggregation": "", + "custom_label": "", + "label": "", + "name": "", + "side": "right", + "type": "", + }, + ], + "yaxis": Array [ + Object { + "label": "avg(FlightDelayMin)", + "name": "avg(FlightDelayMin)", + "type": "double", + }, + Object { + "label": "Carrier", "name": "Carrier", "type": "keyword", }, - ], - "yaxis": Array [ + ], + }, + "explorer": Object { + "explorerData": Object { + "data": Object { + "Carrier": Array [ + "BeatsWest", + "Logstash Airways", + "OpenSearch Dashboards Airlines", + "OpenSearch-Air", + ], + "avg(FlightDelayMin)": Array [ + 53.65384615384615, + 45.36144578313253, + 63.1578947368421, + 46.81318681318681, + ], + }, + "jsonData": Array [ + Object { + "Carrier": "BeatsWest", + "avg(FlightDelayMin)": 53.65384615384615, + }, + Object { + "Carrier": "Logstash Airways", + "avg(FlightDelayMin)": 45.36144578313253, + }, + Object { + "Carrier": "OpenSearch Dashboards Airlines", + "avg(FlightDelayMin)": 63.1578947368421, + }, + Object { + "Carrier": "OpenSearch-Air", + "avg(FlightDelayMin)": 46.81318681318681, + }, + ], + "metadata": Object { + "fields": Array [ + Object { + "name": "avg(FlightDelayMin)", + "type": "double", + }, + Object { + "name": "Carrier", + "type": "keyword", + }, + ], + }, + "size": 4, + "status": 200, + }, + "explorerFields": Array [ Object { "name": "avg(FlightDelayMin)", "type": "double", }, + Object { + "name": "Carrier", + "type": "keyword", + }, ], }, "indexFields": Object {}, @@ -1145,76 +2235,312 @@ exports[`Utils helper functions renders displayVisualization function 2`] = ` "size": 4, "status": 200, }, - "userConfigs": Object {}, + "userConfigs": Object { + "dataConfig": Object { + "valueOptions": Object { + "dimensions": Array [ + Object { + "aggregation": "", + "custom_label": "", + "label": "", + "name": "", + "side": "right", + "type": "", + }, + ], + "metrics": Array [ + Object { + "label": "avg(FlightDelayMin)", + "name": "avg(FlightDelayMin)", + "type": "double", + }, + Object { + "label": "Carrier", + "name": "Carrier", + "type": "keyword", + }, + ], + }, + }, + }, }, "vis": Object { "category": "Visualizations", - "categoryAxis": "xaxis", + "categoryaxis": "xaxis", "component": [Function], - "editorConfig": Object { + "editorconfig": Object { "panelTabs": Array [ Object { "editor": [Function], "id": "data-panel", "mapTo": "dataConfig", - "name": "Data", + "name": "Style", "sections": Array [ Object { "editor": [Function], - "id": "value_options", - "mapTo": "valueOptions", - "name": "Value options", + "id": "legend", + "mapTo": "legend", + "name": "Legend", "schemas": Array [ Object { "component": null, - "isSingleSelection": true, - "mapTo": "xaxis", - "name": "X-axis", + "mapTo": "showLegend", + "name": "Show legend", + "props": Object { + "defaultSelections": Array [ + Object { + "id": "show", + "name": "Show", + }, + ], + "options": Array [ + Object { + "id": "show", + "name": "Show", + }, + Object { + "id": "hidden", + "name": "Hidden", + }, + ], + }, }, Object { "component": null, - "isSingleSelection": false, - "mapTo": "yaxis", - "name": "Y-axis", + "mapTo": "position", + "name": "Position", + "props": Object { + "defaultSelections": Array [ + Object { + "id": "v", + "name": "Right", + }, + ], + "options": Array [ + Object { + "id": "v", + "name": "Right", + }, + Object { + "id": "h", + "name": "Bottom", + }, + ], + }, + }, + Object { + "component": [Function], + "eleType": "input", + "mapTo": "legendSize", + "name": "Legend size", + "title": "Legend size", }, ], }, Object { "editor": [Function], - "id": "chart_options", - "mapTo": "chartOptions", - "name": "Chart options", + "id": "tooltip_options", + "mapTo": "tooltipOptions", + "name": "Tooltip options", "schemas": Array [ Object { "component": null, - "isSingleSelection": true, - "mapTo": "mode", + "mapTo": "tooltipMode", + "name": "Tooltip mode", + "props": Object { + "defaultSelections": Array [ + Object { + "id": "show", + "name": "Show", + }, + ], + "options": Array [ + Object { + "id": "show", + "name": "Show", + }, + Object { + "id": "hidden", + "name": "Hidden", + }, + ], + }, + }, + Object { + "component": null, + "mapTo": "tooltipText", + "name": "Tooltip text", + "props": Object { + "defaultSelections": Array [ + Object { + "id": "all", + "name": "All", + }, + ], + "options": Array [ + Object { + "id": "all", + "name": "All", + }, + Object { + "id": "x", + "name": "Dimension", + }, + Object { + "id": "y", + "name": "Metrics", + }, + ], + }, + }, + ], + }, + Object { + "editor": [Function], + "id": "chart_styles", + "mapTo": "chartStyles", + "name": "Chart styles", + "schemas": Array [ + Object { + "component": [Function], + "eleType": "buttons", + "mapTo": "style", "name": "Mode", "props": Object { "defaultSelections": Array [ Object { - "modeId": "lines", + "id": "lines", "name": "Lines", }, ], - "dropdownList": Array [ + "options": Array [ Object { - "modeId": "markers", - "name": "Markers", + "id": "lines", + "name": "Lines", }, Object { - "modeId": "lines", - "name": "Lines", + "id": "markers", + "name": "Marker", }, Object { - "modeId": "lines+markers", + "id": "lines+markers", "name": "Lines + Markers", }, ], }, }, + Object { + "component": [Function], + "eleType": "buttons", + "mapTo": "interpolation", + "name": "Interpolation", + "props": Object { + "defaultSelections": Array [ + Object { + "id": "spline", + "name": "Smooth", + }, + ], + "options": Array [ + Object { + "id": "linear", + "name": "Linear", + }, + Object { + "id": "spline", + "name": "Smooth", + }, + Object { + "id": "hv", + "name": "Step before", + }, + Object { + "id": "vh", + "name": "Step after", + }, + ], + }, + }, + Object { + "component": [Function], + "defaultState": 2, + "eleType": "slider", + "mapTo": "lineWidth", + "name": "Line width", + "props": Object { + "max": 10, + }, + }, + Object { + "component": [Function], + "defaultState": 40, + "eleType": "slider", + "mapTo": "fillOpacity", + "name": "Fill opacity", + "props": Object { + "max": 100, + }, + }, + Object { + "component": [Function], + "defaultState": 5, + "eleType": "slider", + "mapTo": "pointSize", + "name": "Point size", + "props": Object { + "max": 40, + }, + }, + Object { + "component": [Function], + "eleType": "input", + "mapTo": "labelSize", + "name": "Label size", + "title": "Label size", + }, + Object { + "component": [Function], + "defaultState": 0, + "eleType": "slider", + "mapTo": "rotateLabels", + "name": "Rotate labels", + "props": Object { + "max": 90, + "min": -90, + "showTicks": true, + "ticks": Array [ + Object { + "label": "-90°", + "value": -90, + }, + Object { + "label": "-45°", + "value": -45, + }, + Object { + "label": "0°", + "value": 0, + }, + Object { + "label": "45°", + "value": 45, + }, + Object { + "label": "90°", + "value": 90, + }, + ], + }, + }, ], }, + Object { + "editor": [Function], + "id": "color-theme", + "mapTo": "colorTheme", + "name": "Color theme", + "schemas": Array [], + }, Object { "defaultState": Array [], "editor": [Function], @@ -1240,18 +2566,18 @@ exports[`Utils helper functions renders displayVisualization function 2`] = ` }, ], }, - "fullLabel": "Line", + "fulllabel": "Time series", "icon": [Function], - "iconType": "visLine", + "icontype": "visLine", "id": "line", - "label": "Line", + "label": "Time series", "name": "line", "selection": Object { "dataLoss": "nothing", }, - "seriesAxis": "yaxis", + "seriesaxis": "yaxis", "type": "line", - "visConfig": Object { + "visconfig": Object { "config": Object { "barmode": "line", "displaylogo": false, @@ -1276,7 +2602,7 @@ exports[`Utils helper functions renders displayVisualization function 2`] = ` "#BD6F26", "#4C636F", ], - "height": 500, + "height": 1180, "legend": Object { "orientation": "v", "traceorder": "normal", @@ -1335,7 +2661,7 @@ exports[`Utils helper functions renders displayVisualization function 2`] = ` "#BD6F26", "#4C636F", ], - "height": 500, + "height": 1180, "legend": Object { "orientation": "v", "traceorder": "normal", @@ -1369,15 +2695,85 @@ exports[`Utils helper functions renders displayVisualization function 2`] = ` "defaultAxes": Object { "xaxis": Array [ Object { + "aggregation": "", + "custom_label": "", + "label": "", + "name": "", + "side": "right", + "type": "", + }, + ], + "yaxis": Array [ + Object { + "label": "avg(FlightDelayMin)", + "name": "avg(FlightDelayMin)", + "type": "double", + }, + Object { + "label": "Carrier", "name": "Carrier", "type": "keyword", }, ], - "yaxis": Array [ + }, + "explorer": Object { + "explorerData": Object { + "data": Object { + "Carrier": Array [ + "BeatsWest", + "Logstash Airways", + "OpenSearch Dashboards Airlines", + "OpenSearch-Air", + ], + "avg(FlightDelayMin)": Array [ + 53.65384615384615, + 45.36144578313253, + 63.1578947368421, + 46.81318681318681, + ], + }, + "jsonData": Array [ + Object { + "Carrier": "BeatsWest", + "avg(FlightDelayMin)": 53.65384615384615, + }, + Object { + "Carrier": "Logstash Airways", + "avg(FlightDelayMin)": 45.36144578313253, + }, + Object { + "Carrier": "OpenSearch Dashboards Airlines", + "avg(FlightDelayMin)": 63.1578947368421, + }, + Object { + "Carrier": "OpenSearch-Air", + "avg(FlightDelayMin)": 46.81318681318681, + }, + ], + "metadata": Object { + "fields": Array [ + Object { + "name": "avg(FlightDelayMin)", + "type": "double", + }, + Object { + "name": "Carrier", + "type": "keyword", + }, + ], + }, + "size": 4, + "status": 200, + }, + "explorerFields": Array [ Object { "name": "avg(FlightDelayMin)", "type": "double", }, + Object { + "name": "Carrier", + "type": "keyword", + }, ], }, "indexFields": Object {}, @@ -1430,76 +2826,312 @@ exports[`Utils helper functions renders displayVisualization function 2`] = ` "size": 4, "status": 200, }, - "userConfigs": Object {}, + "userConfigs": Object { + "dataConfig": Object { + "valueOptions": Object { + "dimensions": Array [ + Object { + "aggregation": "", + "custom_label": "", + "label": "", + "name": "", + "side": "right", + "type": "", + }, + ], + "metrics": Array [ + Object { + "label": "avg(FlightDelayMin)", + "name": "avg(FlightDelayMin)", + "type": "double", + }, + Object { + "label": "Carrier", + "name": "Carrier", + "type": "keyword", + }, + ], + }, + }, + }, }, "vis": Object { "category": "Visualizations", - "categoryAxis": "xaxis", + "categoryaxis": "xaxis", "component": [Function], - "editorConfig": Object { + "editorconfig": Object { "panelTabs": Array [ Object { "editor": [Function], "id": "data-panel", "mapTo": "dataConfig", - "name": "Data", + "name": "Style", "sections": Array [ Object { "editor": [Function], - "id": "value_options", - "mapTo": "valueOptions", - "name": "Value options", + "id": "legend", + "mapTo": "legend", + "name": "Legend", "schemas": Array [ Object { "component": null, - "isSingleSelection": true, - "mapTo": "xaxis", - "name": "X-axis", + "mapTo": "showLegend", + "name": "Show legend", + "props": Object { + "defaultSelections": Array [ + Object { + "id": "show", + "name": "Show", + }, + ], + "options": Array [ + Object { + "id": "show", + "name": "Show", + }, + Object { + "id": "hidden", + "name": "Hidden", + }, + ], + }, }, Object { "component": null, - "isSingleSelection": false, - "mapTo": "yaxis", - "name": "Y-axis", + "mapTo": "position", + "name": "Position", + "props": Object { + "defaultSelections": Array [ + Object { + "id": "v", + "name": "Right", + }, + ], + "options": Array [ + Object { + "id": "v", + "name": "Right", + }, + Object { + "id": "h", + "name": "Bottom", + }, + ], + }, + }, + Object { + "component": [Function], + "eleType": "input", + "mapTo": "legendSize", + "name": "Legend size", + "title": "Legend size", + }, + ], + }, + Object { + "editor": [Function], + "id": "tooltip_options", + "mapTo": "tooltipOptions", + "name": "Tooltip options", + "schemas": Array [ + Object { + "component": null, + "mapTo": "tooltipMode", + "name": "Tooltip mode", + "props": Object { + "defaultSelections": Array [ + Object { + "id": "show", + "name": "Show", + }, + ], + "options": Array [ + Object { + "id": "show", + "name": "Show", + }, + Object { + "id": "hidden", + "name": "Hidden", + }, + ], + }, + }, + Object { + "component": null, + "mapTo": "tooltipText", + "name": "Tooltip text", + "props": Object { + "defaultSelections": Array [ + Object { + "id": "all", + "name": "All", + }, + ], + "options": Array [ + Object { + "id": "all", + "name": "All", + }, + Object { + "id": "x", + "name": "Dimension", + }, + Object { + "id": "y", + "name": "Metrics", + }, + ], + }, }, ], }, Object { "editor": [Function], - "id": "chart_options", - "mapTo": "chartOptions", - "name": "Chart options", + "id": "chart_styles", + "mapTo": "chartStyles", + "name": "Chart styles", "schemas": Array [ Object { - "component": null, - "isSingleSelection": true, - "mapTo": "mode", + "component": [Function], + "eleType": "buttons", + "mapTo": "style", "name": "Mode", "props": Object { "defaultSelections": Array [ Object { - "modeId": "lines", + "id": "lines", "name": "Lines", }, ], - "dropdownList": Array [ + "options": Array [ Object { - "modeId": "markers", - "name": "Markers", + "id": "lines", + "name": "Lines", }, Object { - "modeId": "lines", - "name": "Lines", + "id": "markers", + "name": "Marker", }, Object { - "modeId": "lines+markers", + "id": "lines+markers", "name": "Lines + Markers", }, ], }, }, + Object { + "component": [Function], + "eleType": "buttons", + "mapTo": "interpolation", + "name": "Interpolation", + "props": Object { + "defaultSelections": Array [ + Object { + "id": "spline", + "name": "Smooth", + }, + ], + "options": Array [ + Object { + "id": "linear", + "name": "Linear", + }, + Object { + "id": "spline", + "name": "Smooth", + }, + Object { + "id": "hv", + "name": "Step before", + }, + Object { + "id": "vh", + "name": "Step after", + }, + ], + }, + }, + Object { + "component": [Function], + "defaultState": 2, + "eleType": "slider", + "mapTo": "lineWidth", + "name": "Line width", + "props": Object { + "max": 10, + }, + }, + Object { + "component": [Function], + "defaultState": 40, + "eleType": "slider", + "mapTo": "fillOpacity", + "name": "Fill opacity", + "props": Object { + "max": 100, + }, + }, + Object { + "component": [Function], + "defaultState": 5, + "eleType": "slider", + "mapTo": "pointSize", + "name": "Point size", + "props": Object { + "max": 40, + }, + }, + Object { + "component": [Function], + "eleType": "input", + "mapTo": "labelSize", + "name": "Label size", + "title": "Label size", + }, + Object { + "component": [Function], + "defaultState": 0, + "eleType": "slider", + "mapTo": "rotateLabels", + "name": "Rotate labels", + "props": Object { + "max": 90, + "min": -90, + "showTicks": true, + "ticks": Array [ + Object { + "label": "-90°", + "value": -90, + }, + Object { + "label": "-45°", + "value": -45, + }, + Object { + "label": "0°", + "value": 0, + }, + Object { + "label": "45°", + "value": 45, + }, + Object { + "label": "90°", + "value": 90, + }, + ], + }, + }, ], }, + Object { + "editor": [Function], + "id": "color-theme", + "mapTo": "colorTheme", + "name": "Color theme", + "schemas": Array [], + }, Object { "defaultState": Array [], "editor": [Function], @@ -1525,18 +3157,18 @@ exports[`Utils helper functions renders displayVisualization function 2`] = ` }, ], }, - "fullLabel": "Line", + "fulllabel": "Time series", "icon": [Function], - "iconType": "visLine", + "icontype": "visLine", "id": "line", - "label": "Line", + "label": "Time series", "name": "line", "selection": Object { "dataLoss": "nothing", }, - "seriesAxis": "yaxis", + "seriesaxis": "yaxis", "type": "line", - "visConfig": Object { + "visconfig": Object { "config": Object { "barmode": "line", "displaylogo": false, @@ -1561,7 +3193,7 @@ exports[`Utils helper functions renders displayVisualization function 2`] = ` "#BD6F26", "#4C636F", ], - "height": 500, + "height": 1180, "legend": Object { "orientation": "v", "traceorder": "normal", @@ -1592,186 +3224,83 @@ exports[`Utils helper functions renders displayVisualization function 2`] = ` } } > - -
- - + className="euiText euiText--extraSmall lnsChart__empty" + data-test-subj="vizWorkspace__noData" + > + +
+ +
+ + + + + + +
+ +

+ + + No results found + + +

+
+ +
+ +
+ + @@ -1788,15 +3317,77 @@ exports[`Utils helper functions renders displayVisualization function 3`] = ` "defaultAxes": Object { "xaxis": Array [ Object { + "label": "Carrier", "name": "Carrier", "type": "keyword", }, ], "yaxis": Array [ + Object { + "label": "avg(FlightDelayMin)", + "name": "avg(FlightDelayMin)", + "type": "double", + }, + ], + }, + "explorer": Object { + "explorerData": Object { + "data": Object { + "Carrier": Array [ + "BeatsWest", + "Logstash Airways", + "OpenSearch Dashboards Airlines", + "OpenSearch-Air", + ], + "avg(FlightDelayMin)": Array [ + 53.65384615384615, + 45.36144578313253, + 63.1578947368421, + 46.81318681318681, + ], + }, + "jsonData": Array [ + Object { + "Carrier": "BeatsWest", + "avg(FlightDelayMin)": 53.65384615384615, + }, + Object { + "Carrier": "Logstash Airways", + "avg(FlightDelayMin)": 45.36144578313253, + }, + Object { + "Carrier": "OpenSearch Dashboards Airlines", + "avg(FlightDelayMin)": 63.1578947368421, + }, + Object { + "Carrier": "OpenSearch-Air", + "avg(FlightDelayMin)": 46.81318681318681, + }, + ], + "metadata": Object { + "fields": Array [ + Object { + "name": "avg(FlightDelayMin)", + "type": "double", + }, + Object { + "name": "Carrier", + "type": "keyword", + }, + ], + }, + "size": 4, + "status": 200, + }, + "explorerFields": Array [ Object { "name": "avg(FlightDelayMin)", "type": "double", }, + Object { + "name": "Carrier", + "type": "keyword", + }, ], }, "indexFields": Object {}, @@ -1846,22 +3437,41 @@ exports[`Utils helper functions renders displayVisualization function 3`] = ` }, ], }, - "size": 4, - "status": 200, + "size": 4, + "status": 200, + }, + "userConfigs": Object { + "dataConfig": Object { + "valueOptions": Object { + "dimensions": Array [ + Object { + "label": "Carrier", + "name": "Carrier", + "type": "keyword", + }, + ], + "metrics": Array [ + Object { + "label": "avg(FlightDelayMin)", + "name": "avg(FlightDelayMin)", + "type": "double", + }, + ], + }, + }, }, - "userConfigs": Object {}, }, "vis": Object { "category": "Visualizations", - "categoryAxis": "xaxis", + "categoryaxis": "xaxis", "component": [Function], - "editorConfig": Object { + "editorconfig": Object { "panelTabs": Array [ Object { "editor": [Function], "id": "data-panel", "mapTo": "dataConfig", - "name": "Data", + "name": "Style", "sections": Array [ Object { "editor": [Function], @@ -1950,9 +3560,9 @@ exports[`Utils helper functions renders displayVisualization function 3`] = ` }, ], }, - "fullLabel": "Bar", + "fulllabel": "Bar", "icon": [Function], - "iconType": "visBarVerticalStacked", + "icontype": "visBarVerticalStacked", "id": "horizontal_bar", "label": "Bar", "name": "horizontal_bar", @@ -1960,16 +3570,16 @@ exports[`Utils helper functions renders displayVisualization function 3`] = ` "selection": Object { "dataLoss": "nothing", }, - "seriesAxis": "yaxis", + "seriesaxis": "yaxis", "type": "bar", - "visConfig": Object { + "visconfig": Object { "config": Object { "displaylogo": false, "responsive": true, }, "isUniColor": false, "layout": Object { - "height": 500, + "height": 1180, "legend": Object { "orientation": "v", "traceorder": "normal", @@ -1996,15 +3606,77 @@ exports[`Utils helper functions renders displayVisualization function 3`] = ` "defaultAxes": Object { "xaxis": Array [ Object { + "label": "Carrier", "name": "Carrier", "type": "keyword", }, ], "yaxis": Array [ + Object { + "label": "avg(FlightDelayMin)", + "name": "avg(FlightDelayMin)", + "type": "double", + }, + ], + }, + "explorer": Object { + "explorerData": Object { + "data": Object { + "Carrier": Array [ + "BeatsWest", + "Logstash Airways", + "OpenSearch Dashboards Airlines", + "OpenSearch-Air", + ], + "avg(FlightDelayMin)": Array [ + 53.65384615384615, + 45.36144578313253, + 63.1578947368421, + 46.81318681318681, + ], + }, + "jsonData": Array [ + Object { + "Carrier": "BeatsWest", + "avg(FlightDelayMin)": 53.65384615384615, + }, + Object { + "Carrier": "Logstash Airways", + "avg(FlightDelayMin)": 45.36144578313253, + }, + Object { + "Carrier": "OpenSearch Dashboards Airlines", + "avg(FlightDelayMin)": 63.1578947368421, + }, + Object { + "Carrier": "OpenSearch-Air", + "avg(FlightDelayMin)": 46.81318681318681, + }, + ], + "metadata": Object { + "fields": Array [ + Object { + "name": "avg(FlightDelayMin)", + "type": "double", + }, + Object { + "name": "Carrier", + "type": "keyword", + }, + ], + }, + "size": 4, + "status": 200, + }, + "explorerFields": Array [ Object { "name": "avg(FlightDelayMin)", "type": "double", }, + Object { + "name": "Carrier", + "type": "keyword", + }, ], }, "indexFields": Object {}, @@ -2057,19 +3729,38 @@ exports[`Utils helper functions renders displayVisualization function 3`] = ` "size": 4, "status": 200, }, - "userConfigs": Object {}, + "userConfigs": Object { + "dataConfig": Object { + "valueOptions": Object { + "dimensions": Array [ + Object { + "label": "Carrier", + "name": "Carrier", + "type": "keyword", + }, + ], + "metrics": Array [ + Object { + "label": "avg(FlightDelayMin)", + "name": "avg(FlightDelayMin)", + "type": "double", + }, + ], + }, + }, + }, }, "vis": Object { "category": "Visualizations", - "categoryAxis": "xaxis", + "categoryaxis": "xaxis", "component": [Function], - "editorConfig": Object { + "editorconfig": Object { "panelTabs": Array [ Object { "editor": [Function], "id": "data-panel", "mapTo": "dataConfig", - "name": "Data", + "name": "Style", "sections": Array [ Object { "editor": [Function], @@ -2158,9 +3849,9 @@ exports[`Utils helper functions renders displayVisualization function 3`] = ` }, ], }, - "fullLabel": "Bar", + "fulllabel": "Bar", "icon": [Function], - "iconType": "visBarVerticalStacked", + "icontype": "visBarVerticalStacked", "id": "horizontal_bar", "label": "Bar", "name": "horizontal_bar", @@ -2168,16 +3859,16 @@ exports[`Utils helper functions renders displayVisualization function 3`] = ` "selection": Object { "dataLoss": "nothing", }, - "seriesAxis": "yaxis", + "seriesaxis": "yaxis", "type": "bar", - "visConfig": Object { + "visconfig": Object { "config": Object { "displaylogo": false, "responsive": true, }, "isUniColor": false, "layout": Object { - "height": 500, + "height": 1180, "legend": Object { "orientation": "v", "traceorder": "normal", @@ -2205,7 +3896,7 @@ exports[`Utils helper functions renders displayVisualization function 3`] = ` } layout={ Object { - "height": 500, + "height": 1180, "legend": Object { "orientation": "v", "traceorder": "normal", @@ -2227,15 +3918,77 @@ exports[`Utils helper functions renders displayVisualization function 3`] = ` "defaultAxes": Object { "xaxis": Array [ Object { + "label": "Carrier", "name": "Carrier", "type": "keyword", }, ], "yaxis": Array [ + Object { + "label": "avg(FlightDelayMin)", + "name": "avg(FlightDelayMin)", + "type": "double", + }, + ], + }, + "explorer": Object { + "explorerData": Object { + "data": Object { + "Carrier": Array [ + "BeatsWest", + "Logstash Airways", + "OpenSearch Dashboards Airlines", + "OpenSearch-Air", + ], + "avg(FlightDelayMin)": Array [ + 53.65384615384615, + 45.36144578313253, + 63.1578947368421, + 46.81318681318681, + ], + }, + "jsonData": Array [ + Object { + "Carrier": "BeatsWest", + "avg(FlightDelayMin)": 53.65384615384615, + }, + Object { + "Carrier": "Logstash Airways", + "avg(FlightDelayMin)": 45.36144578313253, + }, + Object { + "Carrier": "OpenSearch Dashboards Airlines", + "avg(FlightDelayMin)": 63.1578947368421, + }, + Object { + "Carrier": "OpenSearch-Air", + "avg(FlightDelayMin)": 46.81318681318681, + }, + ], + "metadata": Object { + "fields": Array [ + Object { + "name": "avg(FlightDelayMin)", + "type": "double", + }, + Object { + "name": "Carrier", + "type": "keyword", + }, + ], + }, + "size": 4, + "status": 200, + }, + "explorerFields": Array [ Object { "name": "avg(FlightDelayMin)", "type": "double", }, + Object { + "name": "Carrier", + "type": "keyword", + }, ], }, "indexFields": Object {}, @@ -2288,19 +4041,38 @@ exports[`Utils helper functions renders displayVisualization function 3`] = ` "size": 4, "status": 200, }, - "userConfigs": Object {}, + "userConfigs": Object { + "dataConfig": Object { + "valueOptions": Object { + "dimensions": Array [ + Object { + "label": "Carrier", + "name": "Carrier", + "type": "keyword", + }, + ], + "metrics": Array [ + Object { + "label": "avg(FlightDelayMin)", + "name": "avg(FlightDelayMin)", + "type": "double", + }, + ], + }, + }, + }, }, "vis": Object { "category": "Visualizations", - "categoryAxis": "xaxis", + "categoryaxis": "xaxis", "component": [Function], - "editorConfig": Object { + "editorconfig": Object { "panelTabs": Array [ Object { "editor": [Function], "id": "data-panel", "mapTo": "dataConfig", - "name": "Data", + "name": "Style", "sections": Array [ Object { "editor": [Function], @@ -2365,238 +4137,142 @@ exports[`Utils helper functions renders displayVisualization function 3`] = ` }, ], "dropdownList": Array [ - Object { - "modeId": "group", - "name": "Group", - }, - Object { - "modeId": "stack", - "name": "Stack", - }, - ], - }, - }, - ], - }, - ], - }, - Object { - "content": Array [], - "editor": [Function], - "id": "style-panel", - "mapTo": "layoutConfig", - "name": "Layout", - }, - ], - }, - "fullLabel": "Bar", - "icon": [Function], - "iconType": "visBarVerticalStacked", - "id": "horizontal_bar", - "label": "Bar", - "name": "horizontal_bar", - "orientation": "h", - "selection": Object { - "dataLoss": "nothing", - }, - "seriesAxis": "yaxis", - "type": "bar", - "visConfig": Object { - "config": Object { - "displaylogo": false, - "responsive": true, - }, - "isUniColor": false, - "layout": Object { - "height": 500, - "legend": Object { - "orientation": "v", - "traceorder": "normal", - }, - "margin": Object { - "b": 30, - "l": 60, - "pad": 0, - "r": 30, - "t": 50, - }, - "showlegend": true, - }, - }, - }, - } - } - > - - + +
- - + className="euiText euiText--extraSmall lnsChart__empty" + data-test-subj="vizWorkspace__noData" + > + +
+ +
+ + + + + + +
+ +

+ + + No results found + + +

+
+ +
+ +
+ + @@ -2613,15 +4289,50 @@ exports[`Utils helper functions renders displayVisualization function 4`] = ` "defaultAxes": Object { "xaxis": Array [ Object { + "label": "span(timestamp,1h)", "name": "span(timestamp,1h)", "type": "timestamp", }, ], "yaxis": Array [ + Object { + "label": "count('ip')", + "name": "count('ip')", + "type": "integer", + }, + ], + }, + "explorer": Object { + "explorerData": Object { + "data": Object { + "count('ip')": Array [], + "span(timestamp,1h)": Array [], + }, + "jsonData": Array [], + "metadata": Object { + "fields": Array [ + Object { + "name": "count('ip')", + "type": "integer", + }, + Object { + "name": "span(timestamp,1h)", + "type": "timestamp", + }, + ], + }, + "size": 0, + "status": 200, + }, + "explorerFields": Array [ Object { "name": "count('ip')", "type": "integer", }, + Object { + "name": "span(timestamp,1h)", + "type": "timestamp", + }, ], }, "indexFields": Object {}, @@ -2647,19 +4358,38 @@ exports[`Utils helper functions renders displayVisualization function 4`] = ` "size": 0, "status": 200, }, - "userConfigs": Object {}, + "userConfigs": Object { + "dataConfig": Object { + "valueOptions": Object { + "dimensions": Array [ + Object { + "label": "span(timestamp,1h)", + "name": "span(timestamp,1h)", + "type": "timestamp", + }, + ], + "metrics": Array [ + Object { + "label": "count('ip')", + "name": "count('ip')", + "type": "integer", + }, + ], + }, + }, + }, }, "vis": Object { "category": "Visualizations", - "categoryAxis": "xaxis", + "categoryaxis": "xaxis", "component": [Function], - "editorConfig": Object { + "editorconfig": Object { "panelTabs": Array [ Object { "editor": [Function], "id": "data-panel", "mapTo": "dataConfig", - "name": "Data", + "name": "Style", "sections": Array [ Object { "editor": [Function], @@ -2748,9 +4478,9 @@ exports[`Utils helper functions renders displayVisualization function 4`] = ` }, ], }, - "fullLabel": "Bar", + "fulllabel": "Bar", "icon": [Function], - "iconType": "visBarVerticalStacked", + "icontype": "visBarVerticalStacked", "id": "horizontal_bar", "label": "Bar", "name": "horizontal_bar", @@ -2758,16 +4488,16 @@ exports[`Utils helper functions renders displayVisualization function 4`] = ` "selection": Object { "dataLoss": "nothing", }, - "seriesAxis": "yaxis", + "seriesaxis": "yaxis", "type": "bar", - "visConfig": Object { + "visconfig": Object { "config": Object { "displaylogo": false, "responsive": true, }, "isUniColor": false, "layout": Object { - "height": 500, + "height": 1180, "legend": Object { "orientation": "v", "traceorder": "normal", @@ -2794,15 +4524,50 @@ exports[`Utils helper functions renders displayVisualization function 4`] = ` "defaultAxes": Object { "xaxis": Array [ Object { + "label": "span(timestamp,1h)", "name": "span(timestamp,1h)", "type": "timestamp", }, ], "yaxis": Array [ + Object { + "label": "count('ip')", + "name": "count('ip')", + "type": "integer", + }, + ], + }, + "explorer": Object { + "explorerData": Object { + "data": Object { + "count('ip')": Array [], + "span(timestamp,1h)": Array [], + }, + "jsonData": Array [], + "metadata": Object { + "fields": Array [ + Object { + "name": "count('ip')", + "type": "integer", + }, + Object { + "name": "span(timestamp,1h)", + "type": "timestamp", + }, + ], + }, + "size": 0, + "status": 200, + }, + "explorerFields": Array [ Object { "name": "count('ip')", "type": "integer", }, + Object { + "name": "span(timestamp,1h)", + "type": "timestamp", + }, ], }, "indexFields": Object {}, @@ -2828,19 +4593,38 @@ exports[`Utils helper functions renders displayVisualization function 4`] = ` "size": 0, "status": 200, }, - "userConfigs": Object {}, + "userConfigs": Object { + "dataConfig": Object { + "valueOptions": Object { + "dimensions": Array [ + Object { + "label": "span(timestamp,1h)", + "name": "span(timestamp,1h)", + "type": "timestamp", + }, + ], + "metrics": Array [ + Object { + "label": "count('ip')", + "name": "count('ip')", + "type": "integer", + }, + ], + }, + }, + }, }, "vis": Object { "category": "Visualizations", - "categoryAxis": "xaxis", + "categoryaxis": "xaxis", "component": [Function], - "editorConfig": Object { + "editorconfig": Object { "panelTabs": Array [ Object { "editor": [Function], "id": "data-panel", "mapTo": "dataConfig", - "name": "Data", + "name": "Style", "sections": Array [ Object { "editor": [Function], @@ -2929,9 +4713,9 @@ exports[`Utils helper functions renders displayVisualization function 4`] = ` }, ], }, - "fullLabel": "Bar", + "fulllabel": "Bar", "icon": [Function], - "iconType": "visBarVerticalStacked", + "icontype": "visBarVerticalStacked", "id": "horizontal_bar", "label": "Bar", "name": "horizontal_bar", @@ -2939,16 +4723,16 @@ exports[`Utils helper functions renders displayVisualization function 4`] = ` "selection": Object { "dataLoss": "nothing", }, - "seriesAxis": "yaxis", + "seriesaxis": "yaxis", "type": "bar", - "visConfig": Object { + "visconfig": Object { "config": Object { "displaylogo": false, "responsive": true, }, "isUniColor": false, "layout": Object { - "height": 500, + "height": 1180, "legend": Object { "orientation": "v", "traceorder": "normal", @@ -2976,7 +4760,7 @@ exports[`Utils helper functions renders displayVisualization function 4`] = ` } layout={ Object { - "height": 500, + "height": 1180, "legend": Object { "orientation": "v", "traceorder": "normal", @@ -2998,15 +4782,50 @@ exports[`Utils helper functions renders displayVisualization function 4`] = ` "defaultAxes": Object { "xaxis": Array [ Object { + "label": "span(timestamp,1h)", "name": "span(timestamp,1h)", "type": "timestamp", }, ], "yaxis": Array [ + Object { + "label": "count('ip')", + "name": "count('ip')", + "type": "integer", + }, + ], + }, + "explorer": Object { + "explorerData": Object { + "data": Object { + "count('ip')": Array [], + "span(timestamp,1h)": Array [], + }, + "jsonData": Array [], + "metadata": Object { + "fields": Array [ + Object { + "name": "count('ip')", + "type": "integer", + }, + Object { + "name": "span(timestamp,1h)", + "type": "timestamp", + }, + ], + }, + "size": 0, + "status": 200, + }, + "explorerFields": Array [ Object { "name": "count('ip')", "type": "integer", }, + Object { + "name": "span(timestamp,1h)", + "type": "timestamp", + }, ], }, "indexFields": Object {}, @@ -3032,19 +4851,38 @@ exports[`Utils helper functions renders displayVisualization function 4`] = ` "size": 0, "status": 200, }, - "userConfigs": Object {}, + "userConfigs": Object { + "dataConfig": Object { + "valueOptions": Object { + "dimensions": Array [ + Object { + "label": "span(timestamp,1h)", + "name": "span(timestamp,1h)", + "type": "timestamp", + }, + ], + "metrics": Array [ + Object { + "label": "count('ip')", + "name": "count('ip')", + "type": "integer", + }, + ], + }, + }, + }, }, "vis": Object { "category": "Visualizations", - "categoryAxis": "xaxis", + "categoryaxis": "xaxis", "component": [Function], - "editorConfig": Object { + "editorconfig": Object { "panelTabs": Array [ Object { "editor": [Function], "id": "data-panel", "mapTo": "dataConfig", - "name": "Data", + "name": "Style", "sections": Array [ Object { "editor": [Function], @@ -3133,9 +4971,9 @@ exports[`Utils helper functions renders displayVisualization function 4`] = ` }, ], }, - "fullLabel": "Bar", + "fulllabel": "Bar", "icon": [Function], - "iconType": "visBarVerticalStacked", + "icontype": "visBarVerticalStacked", "id": "horizontal_bar", "label": "Bar", "name": "horizontal_bar", @@ -3143,16 +4981,16 @@ exports[`Utils helper functions renders displayVisualization function 4`] = ` "selection": Object { "dataLoss": "nothing", }, - "seriesAxis": "yaxis", + "seriesaxis": "yaxis", "type": "bar", - "visConfig": Object { + "visconfig": Object { "config": Object { "displaylogo": false, "responsive": true, }, "isUniColor": false, "layout": Object { - "height": 500, + "height": 1180, "legend": Object { "orientation": "v", "traceorder": "normal", @@ -3171,146 +5009,80 @@ exports[`Utils helper functions renders displayVisualization function 4`] = ` } } > - - +
- - + className="euiText euiText--extraSmall lnsChart__empty" + data-test-subj="vizWorkspace__noData" + > + +
+ +
+ + + + + + +
+ +

+ + + No results found + + +

+
+ +
+ +
+ + diff --git a/dashboards-observability/public/components/custom_panels/helpers/__tests__/modal_container.test.tsx b/dashboards-observability/public/components/custom_panels/helpers/__tests__/modal_container.test.tsx index 1127b8f8a..0fb8c3bb0 100644 --- a/dashboards-observability/public/components/custom_panels/helpers/__tests__/modal_container.test.tsx +++ b/dashboards-observability/public/components/custom_panels/helpers/__tests__/modal_container.test.tsx @@ -5,8 +5,9 @@ import { configure, shallow } from 'enzyme'; import Adapter from 'enzyme-adapter-react-16'; +import { DeleteModal } from '../../../common/helpers/delete_modal'; import React from 'react'; -import { getCloneModal, getDeleteModal, DeletePanelModal } from '../modal_containers'; +import { getCloneModal, getDeleteModal } from '../modal_containers'; describe('Modal Container component', () => { configure({ adapter: new Adapter() }); @@ -28,13 +29,13 @@ describe('Modal Container component', () => { expect(wrapper).toMatchSnapshot(); }); - it('renders DeletePanelModal component', () => { + it('renders DeleteModal component', () => { const onCancel = jest.fn(); const onConfirm = jest.fn(); const title = 'Test Title'; const message = 'Test Message'; const wrapper = shallow( - + ); expect(wrapper).toMatchSnapshot(); }); diff --git a/dashboards-observability/public/components/custom_panels/helpers/modal_containers.tsx b/dashboards-observability/public/components/custom_panels/helpers/modal_containers.tsx index e403d88bb..0fb80a597 100644 --- a/dashboards-observability/public/components/custom_panels/helpers/modal_containers.tsx +++ b/dashboards-observability/public/components/custom_panels/helpers/modal_containers.tsx @@ -105,61 +105,3 @@ export const getDeleteModal = ( ); }; - -export const DeletePanelModal = ({ - onCancel, - onConfirm, - title, - message, -}: { - onCancel: ( - event?: React.KeyboardEvent | React.MouseEvent - ) => void; - onConfirm: (event?: React.MouseEvent) => void; - title: string; - message: string; -}) => { - const [value, setValue] = useState(''); - const onChange = (e: React.ChangeEvent) => { - setValue(e.target.value); - }; - return ( - - - - {title} - - - - {message} - The action cannot be undone. - - - - onChange(e)} - data-test-subj="popoverModal__deleteTextInput" - /> - - - - - - Cancel - onConfirm()} - color="danger" - fill - disabled={value !== 'delete'} - data-test-subj="popoverModal__deleteButton" - > - Delete - - - - - ); -}; diff --git a/dashboards-observability/public/components/custom_panels/helpers/utils.tsx b/dashboards-observability/public/components/custom_panels/helpers/utils.tsx index 3121ddeee..8f4465d8e 100644 --- a/dashboards-observability/public/components/custom_panels/helpers/utils.tsx +++ b/dashboards-observability/public/components/custom_panels/helpers/utils.tsx @@ -300,6 +300,7 @@ export const displayVisualization = (metaData: any, data: any, type: string) => query: {}, indexFields: {}, userConfigs: metaData.user_configs, + explorer: { explorerData: data, explorerFields: data.metadata.fields }, })} /> ); diff --git a/dashboards-observability/public/components/custom_panels/panel_modules/panel_grid/panel_grid.tsx b/dashboards-observability/public/components/custom_panels/panel_modules/panel_grid/panel_grid.tsx index cc529f862..dc70ba7fd 100644 --- a/dashboards-observability/public/components/custom_panels/panel_modules/panel_grid/panel_grid.tsx +++ b/dashboards-observability/public/components/custom_panels/panel_modules/panel_grid/panel_grid.tsx @@ -27,6 +27,7 @@ const ResponsiveGridLayout = WidthProvider(Responsive); * http: http core service; * chrome: chrome core service; * panelId: OpenPanel Id + * updateAvailabilityVizId: function to update application if availabilityViz is removed from panel * panelVisualizations: list of panel visualizations * setPanelVisualizations: function to set panel visualizations * editMode: boolean to check if the panel is in edit mode @@ -168,7 +169,7 @@ export const PanelGrid = (props: PanelGridProps) => { _.omit(layout, ['static', 'moved']) ); saveVisualizationLayouts(panelId, visualizationParams); - if (!_.isEmpty(updateAvailabilityVizId)) { + if (updateAvailabilityVizId) { updateAvailabilityVizId(panelVisualizations); } } diff --git a/dashboards-observability/public/components/custom_panels/panel_modules/visualization_flyout/__tests__/__snapshots__/visualization_flyout.test.tsx.snap b/dashboards-observability/public/components/custom_panels/panel_modules/visualization_flyout/__tests__/__snapshots__/visualization_flyout.test.tsx.snap index 9dda6a3ab..3c4bda7a0 100644 --- a/dashboards-observability/public/components/custom_panels/panel_modules/visualization_flyout/__tests__/__snapshots__/visualization_flyout.test.tsx.snap +++ b/dashboards-observability/public/components/custom_panels/panel_modules/visualization_flyout/__tests__/__snapshots__/visualization_flyout.test.tsx.snap @@ -92,7 +92,7 @@ exports[`Visualization Flyout Component renders add visualization Flyout 1`] = ` ownFocus={false} size="m" > - @@ -1319,7 +1319,7 @@ exports[`Visualization Flyout Component renders replace visualization Flyout 1`] ownFocus={false} size="m" > - diff --git a/dashboards-observability/public/components/event_analytics/explorer/explorer.tsx b/dashboards-observability/public/components/event_analytics/explorer/explorer.tsx index a7fd42262..b1c2751f5 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/explorer.tsx +++ b/dashboards-observability/public/components/event_analytics/explorer/explorer.tsx @@ -66,6 +66,7 @@ import { selectFields, updateFields, sortFields } from '../redux/slices/field_sl import { updateTabName } from '../redux/slices/query_tab_slice'; import { selectCountDistribution } from '../redux/slices/count_distribution_slice'; import { selectExplorerVisualization } from '../redux/slices/visualization_slice'; +import { change as changeVizConfig } from '../redux/slices/viualization_config_slice'; import { selectVisualizationConfig, change as changeVisualizationConfig, @@ -77,6 +78,7 @@ import { getVizContainerProps } from '../../visualizations/charts/helpers'; import { parseGetSuggestions, onItemSelect } from '../../common/search/autocomplete_logic'; import { formatError } from '../utils'; import { sleep } from '../../common/live_tail/live_tail_button'; +import { QueryManager } from '../../../../common/query_manager/ppl_query_manager'; const TYPE_TAB_MAPPING = { [SAVED_QUERY]: TAB_EVENT_ID, @@ -141,6 +143,7 @@ export const Explorer = ({ const [browserTabFocus, setBrowserTabFocus] = useState(true); const [liveTimestamp, setLiveTimestamp] = useState(DATE_PICKER_FORMAT); const [triggerAvailability, setTriggerAvailability] = useState(false); + const [isValidDataConfigOptionSelected, setIsValidDataConfigOptionSelected] = useState(false); const queryRef = useRef(); const appBasedRef = useRef(''); @@ -353,8 +356,21 @@ export const Explorer = ({ // search if (finalQuery.match(PPL_STATS_REGEX)) { + const cusVisIds = userVizConfigs ? Object.keys(userVizConfigs) : []; getVisualizations(); getAvailableFields(`search source=${curIndex}`); + for (const visId of cusVisIds) { + dispatch( + changeVisualizationConfig({ + tabId, + vizId: visId, + data: { + ...userVizConfigs[visId], + dataConfig: {}, + }, + }) + ); + } } else { findAutoInterval(startTime, endTime); if (isLiveTailOnRef.current) { @@ -475,6 +491,7 @@ export const Explorer = ({ handleQuerySearch(availability); }; + /** * Toggle fields between selected and unselected sets * @param field field to be toggled @@ -717,6 +734,7 @@ export const Explorer = ({ indexFields: explorerFields, userConfigs: userVizConfigs[curVisId] || {}, appData: { fromApp: appLogEvents }, + explorer: { explorerData, explorerFields, query, http, pplService }, }); }, [curVisId, explorerVisualizations, explorerFields, query, userVizConfigs]); @@ -727,6 +745,9 @@ export const Explorer = ({ } }; + const changeIsValidConfigOptionState = (isValidConfig: Boolean) => + setIsValidDataConfigOptionSelected(isValidConfig); + const getExplorerVis = () => { return ( ); }; @@ -803,25 +825,55 @@ export const Explorer = ({ const handleQuerySearch = useCallback( async (availability?: boolean) => { + // clear previous selected timestamp when index pattern changes if ( !isEmpty(tempQuery) && !isEmpty(query[RAW_QUERY]) && isIndexPatternChanged(tempQuery, query[RAW_QUERY]) ) { + await updateCurrentTimeStamp(''); } if (availability !== true) { await updateQueryInStore(tempQuery); } - fetchData(); + await fetchData(); + + if (selectedContentTabId === TAB_CHART_ID) { + // parse stats section on every search + const qm = new QueryManager(); + const statsTokens = + qm + .queryParser() + .parse(tempQuery) + .getStats(); + + await dispatch( + changeVizConfig({ + tabId, + vizId: curVisId, + data: { + dataConfig: { + metrics: statsTokens.aggregations.map((agg) => ({ + label: agg.function?.value_expression, + name: agg.function?.value_expression, + aggregation: agg.function?.name, + })), + dimensions: statsTokens.groupby?.group_fields?.map((agg) => ({ + label: agg.name ?? '', + name: agg.name ?? '', + })), + }, + }, + }) + ); + } }, - [tempQuery, query[RAW_QUERY]] + [tempQuery, query, selectedContentTabId] ); - const handleQueryChange = async (newQuery: string) => { - setTempQuery(newQuery); - }; + const handleQueryChange = async (newQuery: string) => setTempQuery(newQuery); const handleSavingObject = async () => { const currQuery = queryRef.current; @@ -835,6 +887,10 @@ export const Explorer = ({ setToast('Name field cannot be empty.', 'danger'); return; } + if (!isValidDataConfigOptionSelected) { + setToast('Invalid value options configuration selected.', 'danger'); + return; + } setIsPanelTextFieldInvalid(false); if (isEqual(selectedContentTabId, TAB_EVENT_ID)) { const isTabMatchingSavedType = isEqual(currQuery![SAVED_OBJECT_TYPE], SAVED_QUERY); @@ -1127,6 +1183,14 @@ export const Explorer = ({ explorerVisualizations, setToast, pplService, + handleQuerySearch, + handleQueryChange, + setTempQuery, + fetchData, + explorerFields, + explorerData, + http, + query }} >
@@ -1162,6 +1226,7 @@ export const Explorer = ({ stopLive={stopLive} setIsLiveTailPopoverOpen={setIsLiveTailPopoverOpen} liveTailName={liveTailNameRef.current} + searchError={explorerVisualizations} /> -
- - -
-
-
- - - - - - - Bar - - - - - - - - - - - - -
- -
-
- -
- -
- - - - - - - - -
-
-
-
- - -
- - -
- -
- - -
- -
- , - "id": "data-panel", - "name": "Data", - } - } - tabs={ - Array [ - Object { - "content": , - "id": "data-panel", - "name": "Data", - }, - Object { - "content": , - "id": "style-panel", - "name": "Layout", + "id": "color-theme", + "mapTo": "colorTheme", + "name": "Color theme", + "schemas": Array [], + }, + ], + }, + Object { + "content": Array [], + "editor": [Function], + "id": "style-panel", + "mapTo": "layoutConfig", + "name": "Layout", + }, + Object { + "editor": [Function], + "id": "availability-panel", + "mapTo": "availabilityConfig", + "name": "Availability", + }, + ], + }, + "fillOpacity": 80, + "fulllabel": "Vertical bar", + "groupwidth": 0.7, + "icon": [Function], + "iconType": "visBarVerticalStacked", + "icontype": "visBarVerticalStacked", + "id": "bar", + "label": "Vertical bar", + "labelangle": 0, + "legendposition": "v", + "linewidth": 1, + "mode": "group", + "name": "bar", + "orientation": "v", + "selection": Object { + "dataLoss": "nothing", + }, + "seriesaxis": "yaxis", + "showlegend": "show", + "type": "bar", + "visconfig": Object { + "config": Object { + "displaylogo": false, + "responsive": true, + }, + "isUniColor": false, + "layout": Object { + "height": 1180, + "legend": Object { + "orientation": "v", + "traceorder": "normal", + }, + "margin": Object { + "b": 30, + "l": 60, + "pad": 0, + "r": 30, + "t": 50, + }, + "showlegend": true, }, + }, + }, + ] + } + singleSelection={true} + sortMatchesBy="none" + > +
+ , - "id": "availability-panel", - "name": "Availability", + ], + }, + Object { + "content": Array [], + "editor": [Function], + "id": "style-panel", + "mapTo": "layoutConfig", + "name": "Layout", + }, + Object { + "editor": [Function], + "id": "availability-panel", + "mapTo": "availabilityConfig", + "name": "Availability", + }, + ], + }, + "fillOpacity": 80, + "fulllabel": "Vertical bar", + "groupwidth": 0.7, + "icon": [Function], + "iconType": "visBarVerticalStacked", + "icontype": "visBarVerticalStacked", + "id": "bar", + "label": "Vertical bar", + "labelangle": 0, + "legendposition": "v", + "linewidth": 1, + "mode": "group", + "name": "bar", + "orientation": "v", + "selection": Object { + "dataLoss": "nothing", + }, + "seriesaxis": "yaxis", + "showlegend": "show", + "type": "bar", + "visconfig": Object { + "config": Object { + "displaylogo": false, + "responsive": true, + }, + "isUniColor": false, + "layout": Object { + "height": 1180, + "legend": Object { + "orientation": "v", + "traceorder": "normal", + }, + "margin": Object { + "b": 30, + "l": 60, + "pad": 0, + "r": 30, + "t": 50, + }, + "showlegend": true, + }, + }, }, ] } + singleSelection={true} + toggleButtonRef={[Function]} + updatePosition={[Function]} + value="Vertical bar" > -
-
- - - - - - - - - -
-
-
- -
- -
- -
-
- - -
-
- -
-
- -
-
- + + + + + + Vertical bar + + + + + + + + + + + + +
+ +
+
+ +
+ +
+ + + +
+
+
+
+ + +
+ + +
+ +
+ + +
+ +
+ , + "id": "data-panel", + "name": "Style", + } + } + tabs={ + Array [ + Object { + "content": , + "id": "data-panel", + "name": "Style", + }, + Object { + "content": , + "id": "style-panel", + "name": "Layout", + }, + Object { + "content": , + "id": "availability-panel", + "name": "Availability", + }, + ] + } + > +
+ +
+ + + + + + + + + +
+
+
+ +
+ +
+ +
+
+ + +
+
+ +
+
+ +
+
+ -
+ +
+
+ + + +
+
+ + +
+
+ + + + +
+
+
+
+ +
+ Name your visualization. +
+
+
+
+
+ +
+
+ + + +
+
+ + +