text:
DASY & DANAS - I2M
decenije - Danas
EMD Uranium - I2M Consulting
EMD Uranium - I2M Associates, LLC
Dec 29, 2015 - 2015 EMD Uranium (Nuclear Minerals and REE) Committee ... Uranium Production in the U.S.- 3rd Quarter, 2015 . ...... Langer Heinrich (NA).
RURALNI TURIZAM HRVATSKE DANAS: GDJE ... - Obrazovni turizam
Committee 2016 EMD Uranium - I2M Associates, LLC
Dec 18, 2016 - Uranium Production in the U.S.- 3rd Quarter, 2016 . .... Bruce Rubin, Senior Geological Consultant, Millers Mills, NY (Founding ...... The SEGF-Hugh E. McKinstry Fund supports "study, research and teaching of .... From a historical per
Author's personal copy - I2M Associates, LLC
i2M musicport Owner's Manual
Intensification of Typhoon Danas (1324) Captured by MTSAT ... - J-Stage
Jun 27 2008 Nbr. 287 Jun 27 2008 by I2M TNX NG3K, ARRL, OPDX ...
FOOD WITHOUT FOSSIL FUELS NOW HRANA BEZ FOSILNIH GORIVA DANAS 139
7 downloads 11 Views 2MB Size Report
Read instruction carefully before starting using of system .... DISPLAY: permits to remotely control DASY, to use a manual switch to start and stop sampling, and.
DASY & DANAS User manual Version 1.32 – January 2008
BASIC PROCEDURE .......................................................................................... 3 PACKAGE CONTENT.......................................................................................... 4 DASY INSTALLATION ........................................................................................ 5 LED INDICATORS................................................................................................ 5 INPUTS ...................................................................................................................... 7 HARDWARE CONFIGURATION .................................................................... 8 SD MEMORY CARD............................................................................................. 8 TECHNICAL CHARACTERISTICS................................................................ 9 GPS: GENERALITIES....................................................................................... 10 DASY AND GPS .................................................................................................. 11 GPS ANTENNAS SPECIFICATION ........................................................... 12 DANAS INSTALLATION.................................................................................. 14 MAIN WINDOW .................................................................................................... 15 DATA LOAD........................................................................................................... 17 3D MAP AREA ..................................................................................................... 20 SESSION MANAGER ....................................................................................... 24 GRAPH AREA....................................................................................................... 26 SETTINGS MENU ............................................................................................... 37 HARDWARE SETTINGS .................................................................................. 37 AUTOCALIBRATION ......................................................................................... 40 SOFTWARE SETTINGS ................................................................................... 40 SENSORS ................................................................................................................ 40 APPENDIX A: RPM, SPEED AND POWER CONNECTIONS ........ 44
Basic Procedure - Read instruction carefully before starting using of system - Install telemetry on the bike - Identify configuration parameters for ach chosen sensor - Using DANAS, configure all hardware parameters - It is now possible to use the data acquisition system
WARNING: DO NOT FIX hardly Dasy to your bike. Vibrations can cause malfunction of the system (recording could be stopped) and occasionally can damage irremediably your SD memory card. We strongly recommend to insulate dasy from the bike and from any vibration sources ATTENTION: If a previous version of DANAS is already installed, use uninstall tool and manually delete the 'Danas' directory (normally situated in C:\Programmi)
ATTENTION: DASY and DANAS are designed for track use only and are not sanctioned for road use.
DASY & DANAS SYSTEM The I2M data acquisition system is composed of two inseparable elements: the acquisition box DASY and the data analysis software DANAS. Here you will find the installation and use instruction of the two elements.
PACKAGE CONTENT DASY package content: - telemetry - GPS receiver - Velcro strip to mount the receiver on the bike - SD memory - CD with instructions and installation software
Cables package content: - cable - stripping quick splice for electrical contact Make sure to create good electrical contacts when mounting. In case of disturbs check the electrical contact. Protect from rain and moisture: wire tarnishing may deteriorate the contact quality. The figure shows the DASY (Data Acquisition SYstem) package: on the front side there are the various input contacts, the GPS connector and the SD memory card slot, protected by a cover.
We advise to connect the cables by soldering (and insulating the contact). Even if using stripping quick splices is a fast and easy way to create a contact, in the long run it may lead to tarnishing and loss of contact.
DASY INSTALLATION On the package's left side there is a fuse holder, already containing a 500 mA fuse. On the same side there is the power supply cable. Dasy is supplied by a three cables system: ground, +12V and +12V under key. In the following picture you can see how to connect the system (using the provided connector) 1) ORANGE = +12V under key 2) BLACK = ground 3) RED = +12V
Red and Black cable have to be directly connected to bike battery. Dasy is in this way continuosly supplied in order to ensure the correct writing opeations on SD memory even in case of an accidental abrupt turning off. Once you have turned off the key Dasy is still connected to the battery but it does not absorb any current avoiding battery discharge. Orange cable must be connected to a power under key or to a distinct switch to turn it on/off Even if Dasy (with 3 cable supply) is protected from an accidental power off, we strongly recommend to wait until the sampling is finished before turning Dasy off
ATTENTION: if DASY is connected to a key-activated supply, or if the system is powered on and off by a switch, keep in mind that switching off the system during a SD memory write operation (indicated by a green light) may cause loss of all data on the memory, and even permanent damage to the memory card. The system stops sampling the inputs when the autostart signal remains in not valid state for at least 3s. Be careful not to switch off power before the system has stopped sampling and ended the write operation.
At power on the three LED indicators on the upper side light up to indicate the system is checking for the presence of a memory card. If an SD card is not present, the system hold all operations. To resume proper operation insert a memory card and power the system off and on. After successfully identifying a memory card, DASY initializes the memory content and prepares for the following samplings. This operation is signaled by the GPS and DATA indicators flashing alternately. After this phase the system is ready to acquire signals. The system may turn into self protection mode (signaled by the three LED indicators remaining on or off indefinitely) in case of a serious voltage drops, for example at power on if the battery is nearly depleted. To avoid this we advise to activate the telemetry system AFTER turning on the bike. If the system is in self protection mode, restart it to resume normal operation.
LED indicators On DASY's upper side there are three LED indicators, two red and one green.
POWER : Indicates if the system is powered on and is working correctly. It is always lighted except in the automatic closure step at the end of a session.
GPS : Indicates GPS peripheral's status. After powering on, it remains lighted to indicate the GPS receiver is not able to calculate valid position; flashes on and off with a 1s-period if working properly. If the satellite signal is poor, the external receiver may obtain a valid position but not a valid speed; the GPS indicator will flash but the speed information will not be accurate. If the memory is full, the GPS and DATA indicator flash alternately.
DATA : Indicates proper data acquisition by emitting a short flash for each memory write operation. Varying the sampling frequency will vary the flashing frequency as well. Do not turn off the data acquisition system if the green indicator is lighted, stop sampling first.
ATTENTION: if all 3 indicators remain on or off indefinitely, the system is in self protection mode. Restart the system.
INPUTS DASY has been designed with versatility in mind. It can be used even with a single input connection, with or without activating the GPS receiver. DASY4 presents the following input connections: -
Front and Rear: intended to be connected to potentiometer on forks or mono; the corresponding connectors have three pins: ground, power supply and analog input. Inputs vary between 0 V and 5 V, and are sampled at 10 bits. Analog1 e Analog2: analog inputs between 0 V and 5 V, sampled at 10 bits. May be used to read analog signals such as throttle opening or brake pressure. RPM: dedicated to measuring the engine rotation speed; can be connected to the signal from the management system to the dashboard. Attention, the number of pulses sent to the dashboard for each engine revolution is different for every bike. IT MUST THEREFORE BE CONFIGURED in DANAS. The system can accept signals up to 20V. SPEED: it can read two speed signals, for example from the two wheels. The signals can be generated by inductive sensors or, for the rear wheel, can be taken directly from the stock sensor. The stock sensor counts pinion revolutions or, less frequently, revolutions of an internal shaft. Attention: the number of pulses per revolutions from such sensors is different for every bike model. IT MUST THEREFORE BE CONFIGURED in DANAS. DISPLAY: permits to remotely control DASY, to use a manual switch to start and stop sampling, and replicate information given by the three LED indicators. IR: connection for an infrared receiver, to obtain a lap synchronization and measure lap times if GPS is not used.
Choose first which inputs to connect, and select a mounting position for DASY. RPM, Speed and Throttle signals can be obtained directly from the dashboard or the management system. The signals can be derived with stripping quick splices or with dedicated cables.
HARDWARE CONFIGURATION The system must be configured using the companion software DANAS (see SETTINGS MENU) before starting acquiring data. It is not necessary to remove DASY from the bike, nor to connect it to a PC; it is sufficient to save all configurations on an SD memory card, the system will read the configurations and store them in a non-volatile memory when first powered on. The available configurations are: - Sampling period: elapsed time between two consecutive sampling. Its inverse is sampling frequency. - Dead Time: when an infrared receiver is used, indicates how much time the system will be insensitive to transmitter signals after successfully receiving a signal. Useful when there is more than one transmitter on the pit wall, prevents multiple START signals to invalidate the lap time measurement. - Speed 1: when the speed is measured by a sensor on pinion or wheel, indicates how many pulses per revolution are generated. - Speed 2: like above, for the second speed signal. - RPM pulses: how many pulses are generated by the management system for each engine revolution. - Start enable: permits to choose which inputs can start the sampling. The sampling can be started when speed is more than zero (speed can be measured from a sensor or GPS), when an IR signal is received, or manually by the remote control. ATTENTION: the signal must be valid for at least 3 seconds before sampling starts, and the sampling is stopped when the signal is invalid for at least 3 seconds. To configure the system follow this steps: - turn on the telemetry system with the memory card inserted to create a blank data file - set the desired parameters - update the data file on the memory card For more detailed information refer to the SETTINGS MENU chapter. When initializing the memory card, all data retained in the system is kept until the memory card is read. So the system remains set in the last configuration.
SD MEMORY CARD The system uses standard 64 Mb SD memory cards. Bigger memory cards can still be used, but only the first 64 Mb will be employed by the system. The memory card is formatted and initialized using a proprietary scheme. Every change in the memory content (data file modifications or extraneous file presence) will be treated by the system as data corruption, so the memory will be reformatted.
ATTENTION: to prevent loss of data do not modify in any way the memory card content. To erase all the memory card content, format the card directly from PC or save a new configuration file (automatically formatted) using DANAS.
ATTENTION: ALWAYS deactivate the memory card reader before disconnecting from PC to prevent damages. Always use Windows' "Safely remove hardware" tool.
ATTENTION: To prevent memory card damage make sure power supply is not interrupted while the system is writing data. The system stops writing when the activating signal is not valid for at least 3 seconds. Do not turn off power before the system has finished writing, leave time to end the write operation. The system is still writing when the green LED indicator is lighted.
TECHNICAL CHARACTERISTICS Power supply: 12-16V Maximum sampling frequency: 50Hz per channel (GPS excluded) Size: 120mm x 70mm x 45mm Weight: 200g + 90g (GPS) Maximum current sourced per sensor: 5mA Digital inputs: Maximum low level voltage = 0.5V Minimum high level voltage = 4.5V Maximum input voltage = 14V 3 PIN INPUT
5 PIN INPUTS
+5V
ANALOG2 FRONT
GND GND
+5V +5V
IN IN
DISP1
DASY does not affect in any way the signals it is connected to. Its inputs present a high impedance. When the system is turned off, the input impedance decreases to 2kΩ. In a few cases such a low impedance may impair the concerned signals. We advise to disconnect DASY when not in use. ATTENTION: every connector contains both GROUND and +5V terminals. Such terminals must not be connected if the signals comes from an active sensor to prevent short circuits. These terminals are used to power passive sensors such as potentiometer on forks.
GPS: Generalities Before analyzing the acquisition system a short introduction to GPS functioning and use should be given. The GPS (Global Positioning System) navigation system has been devised by US Department of Defense to locate a receiver anywhere on the globe with very high accuracy, and to obtain a very accurate time measure. GPS applications are no longer restricted to military use, but are available for civil purposes. The GPS system is made up from three separate parts: the space segment, the control center and the receivers. There is a 24-satellites constellation in orbit, of which 21 are always active and the remaining 3 are used as backups in case of failures. The satellites are in circular orbit at an altitude of about 20200km. From any point on the globe there are always five to eight satellites visible. Each satellite continuously broadcasts two RF signals; one, called L1, carries the "coarse acquisition" positioning signal and the time signal, the other, called L2, carries the "precision acquisition" positioning signal. The signals are broadcasted using phase modulation and three different codes: C/A for coarse acquisition, P for precision acquisition and another for orbit data and other system parameters. Each satellite has a unique modulation code, so the receiver can distinguish signals from different satellites. The C/A signal is generally available, while use of P signal is restricted to subjects authorized by the US Government. Commercial receivers are therefore designed to receive only the L1 signal, and to decode the C/A code, whereas military receivers can receive both L1 and L2, and decode C/A and P codes. Until not so long ago the US Government intentionally kept low the precision obtainable using the C/A code, so civilian applications could not fully exploit the system. Such restriction has been recently removed, at least in part, so in future receiver with a higher precision should become commercially available. A GPS receiver calculates its position by measuring the distances from its antenna to all the visible satellites. At every moment, the position of each satellite is known. To calculate the receiver's position, it is necessary to obtain at least four independent measures, and then solve a system of four equations in four variables (longitude, latitude, elevation and time). The system's solution will be the location of the receiver, obtained with maximum possible precision. The receiver obtains the distance from a satellite by measuring the time of flight of the signals from the satellite to the receiver. This is made possible by synchronizing all the clocks in the whole GPS system. Each satellite carries four atomic clocks, periodically resynchronized from the control center. The receiver cannot obviously contain an atomic clock, but what matters is the short term stability of timing, not the absolute precision. The distance measure obtained is affected by errors due to atmospherical effects on the signal's propagation speed, to limited precision of satellite clocks and other secondary sources. The errors, on average, are of about 2 meters due to imperfections in the satellites' orbits, four meters due to ionosphere and troposphere effects (variable delays in the propagation of signals), and two more meters due to the satellite atomic clocks (an imprecision of even a single nanosecond causes an error of 30 centimeters). Another source of errors, especially when a GPS receiver is used in a city, is the so-called "urban canyoning", the effect of multiple reflections of the satellite signals on building walls. The best precision obtainable in civil measures is about 100m in the horizontal direction, 150m in the vertical direction and 340ns in time. If more then four satellites are directly visible from the receiver, error correction algorithms can be exploited to improve the precision. A single GPS receiver has an horizontal precision of 20 meters for 95% of the time. This precision is so good the US government decided to prohibit the full use to anyone not expressly authorized. This is called Selective Availability (SA), and allows horizontal precisions of 100 meters for 95% of the time. Authorized users have available the PPS (Precise Positioning System) code, not degraded by SA, and can obtain the maximum system precision of about 20 meters.
DASY AND GPS GPS receivers are not all the same. The earlier models, still commercially available and using only 12 or 16 receiving channels, are sufficient when using the receiver in open spaces (race track included). When using in a city, it is advisable to employ a receiver with more receiving channels. DASY uses a latest-generation GPS antenna and the new sensor SiRF Star III, with exceptional sensitivity. The chipset has been designed to work with 20 channels, and optimized for city use and all cases of urban canyoning (cities, mountains, forests, tree-lined avenues, etc…). As previously mentioned, the absolute precision of a GPS receiver is about 10 meters, but the relative precision is much better. This means the a GPS receiver can determine its position with an error of about 10 meters, but then the receiver's movements can be tracked with much smaller errors. For this reason GPS trails are accurate, but comparing the same trail (for example a racing track) obtained in different days may show the same accurate trail but with an offset of several meters. GPS navigators are only apparently more accurate, but this is due to additional information contained in their database: for example they lock the position to the center of a road even when the received signal is several meters off. Another important point for a GPS antenna is the delay in satellite connection. When a receiver is powered on it receives additional data as well as the positioning coordinates from the satellite, and keeps them in memory. This additional data include the ephemeris (the precise position of the satellite and the speed and acceleration used to calculate future positions), the clock corrections, data on the atmosphere (to calculate the propagation speed of the signal) and the status report of the satellites (including if the signal is valid or not, for example if the satellite is being serviced). When a GPS receiver is powered on shortly after a previous use, or loses the signal for a short time, all this additional information is kept in memory and it is still valid, so the first position computation is very fast, taking only a few seconds, and this is called "hot start". When the receiver remains powered off for a longer time the ephemeris are no longer valid, so it will take a longer time to download the data from the satellite, and this is called "warm start". If in memory there is no data at all (for example after a long period of not use) the first valid position is calculated after about a minute, time necessary to download all data from the satellite; this is called "cold start". The antennas used by DASY present very good delays: - HotStart; 8sec (BR305) 1sec (BR355) - WarmStart: 38sec (BR305) 38sec (BR355) - ColdStart: 45sec (BR305) 42sec (BR355) - Reacquisition: 0.1sec (BR305) 0.1sec (BR355) It is important to notice that not all territory is equally covered by a GPS signal, and the coverage is affected by all the errors mentioned previously. Moreover, the speed estimations may be inaccurate, etc.. Both DASY and DANAS do not process the GPS signal, any errors and/or mismatches on the trails or speeds are entirely due to erroneous data received from the antennas. The position and speed data are saved exactly as received. The antennas inaccuracies may cause other undesired effects: for example, if the only telemetry autostart parameter is GPS speed, it may happen that sampling will not start even when the receiver is moving, or that sampling is started even when the receiver is stationary. This is due to errors in the speed estimation, caused by a weak satellite signal. We therefore advise to set another telemetry autostart parameter alongside GPS speed.
ATTENTIONE: Since delay times are very short, we advise to start a session when the GPS signal is already valid. When the receiver is moving satellite acquisition may take longer, and the initial accuracy is very low. So at the start of a session, even when the signal is "valid", there may be large errors in both recorded position and speed.
GPS ANTENNAS SPECIFICATION BR-355
DANAS DANAS (Data ANAlysis Software) processes, visualizes and helps to read the data acquired by DASY.
DANAS INSTALLATION To install DANAS insert the given CD and follow the following steps: • deactivate the antivirus • install Java (if not already installed) by downloading the latest free version from www.java.com (Java can also be installed from the directory JAVA on CD, but the supplied version may not be up to date and we advise to download the installer from the site) • execute danas-installer.exe in the CD's DANAS directory DANAS and the installer are designed and optimized to work under Windows XP, previous version are not supported and proper working is not guaranteed.
ATTENTION: If a previous version of DANAS is already installed, use the uninstall tool and manually remove the directory 'Danas' (usually found in C:\Programmi)
MAIN WINDOW At startup, the main window is divided in three different regions: upper right, upper left and lower. Their dimensions can be modified by dragging the separators.
The upper left quadrant contains the GPS signal map, and typically shows the GPS trails of the trajectory followed on track (hereafter this region will be indicate with 3DMap). The upper right region is made up of two text tabs, which contain all data about the loaded sessions and laps (will be indicated by Session Manager). The lower half will show graphs of all data acquired by telemetry (speed, engine RPM, etc.) (will be indicated by Graphic). The various functions will be explained more in depth below. This manual refers to english names, menus and keywords. However, the main language can be easily changed by choosing 'File Æ Preferences' (more on this below).
At the upper left of the window there is an additional tab that selects 'Session Viewer', which summarizes all loaded data, and in raw format all data for each session. This tab reports: number of loaded sessions, total recorded time, covered distance and, for each recorded signal, the minimum and maximum values and the overall mean:
By choosing a session from the list on the left, a summary of the session and all the raw data relative to the session is shown:
DATA LOAD DANAS processes data saved by the DASY acquisition system. It is therefore necessary, as the first operation, to transfer data from the acquisition system to a DANAS-equipped PC. To do this, simply extract the memory card from DASY and copy the contained text file in a directory. To help users familiarize with the software, example data are preinstalled in the directory …\Danas\Samples\ Start DANAS by double-clicking its icon. Select from the menu
'File' Æ 'Load Session' and navigate to the directory where the data file has been saved. Choose 'Open' (Attention: the preinstalled example data have been recorded using different bikes, so when loading the sessions it is necessary to also load the appropriate settings, by selecting the option LoadSettings from the Settings menu. The settings are contained in …\Danas\Samples and are identified by the cfg extension. When loading data obtained with different settings from those already set in DANAS, the following dialog will appear)
When opening a data file, DANAS processes all the contained sessions, and for each one asks a loading confirmation; it is possible to choose not to load all the recorded sessions, for personal choice or to avoid loading non-valid sessions (for example too short sessions, or sessions with no valid data…) For each session a brief description is shown, containing date, start time, covered distance, GPS signal validity, etc…, permitting to choose if the session is to be loaded or not (we advise not to load nonmeaningful sessions to limit the processing load). The user can click on Yes or No to choose for each session if it is to be loaded, or Yes to all with GPS to load all sessions with valid GPS data. In the lower right corner of the window a progress bar shows the overall progress of the loading. ATTENTION: all indicated times are intended GMT, and are present only with valid GPS signals.
sample of non meaningful session, do not load
sample of meaningful session, load
For every operation, a blue progress bar shows the overall progress
At the left of the progress bar there is a green indicator: clicking on the indicator brings up a window that permits to increase the memory available to DANAS. This can be useful when loading very long sessions, or a large number of sessions.
Multiple files can be loaded, for example to compare data recorded in different days. To do so, repeat the operation described above. DANAS will ask if the user want to delete already loaded sessions: to add other sessions, answer NO. The 'Clear Sessions' option erases all loaded data; the 'Save Sessions' option allows to save all the loaded data, thus excluding all the rejected sessions. The 'Preferences' option allows to choose the language between Italian and English. The change takes place at the next start of DANAS. This option also allows to deselect all the 'Don't show this message again' flags present in some dialog windows. When resetting these flags, all dialog windows will be again shown:
The 'Export' option allows to export the data through a dialog mask. The exported data can be chosen between Laps and Sessions, and between all data and only the selected data. Available formats are CSV (Comma Separated Values, it is possible to choose which signals to export) and KML (compatible with GoogleEarth and GoogleMaps). When exporting in KML and using with GoogleMaps, it is easily noticeable the offset present in the GPS measure.
A confirmation dialog appears when closing the program to prevent accidental loss of data.
3D MAP AREA By default this region shows the trail of GPS trajectories in the whole loaded session. Click on the arrow buttons to pan the map around, and on the + and – buttons to zoom in or out. It is also possible to pan by has dragging with the mouse, and to zoom by moving the mouse wheel, when the Navigation button been activated. Placing the mouse pointer above a button, without clicking, a tooltip appears briefly describing the button function. (Reset, Refresh, DeselectAll) are used to redraw the map with default options, The 3 buttons redraw the map in case of visualization problems and deselect all the selected items.
The buttons below the map are used to activate additional functionalities; they dim when the functionality is active. The button (Selection) is used to select a part of the map: the selected zone is highlighted in yellow. The corresponding graph section is also highlighted.
The button (FinishingLine) is used to place the finish line on the map. The section will be highlighted in white and signaled by a small 'F' near the trajectory.
By pressing the 'Options…' button the user can set the radius of the finish line marker (the number may be rounded by the system). Increasing the radius may help when the trajectories are jagged and all of them can not be covered by the small marker.
The buttons markers.
(AddSplit and RemoveSplit) are used to place on the map, and remove from it, split
Splits are numbered, and the split number is shown beside the marker on the trajectory trail.
ATTENTION: do not place split n+1 spatially before split n along the trajectory, as this may cause errors in the calculations. The system is not able to handle this. If the user forgot to place a split, we advise to remove all the following splits and recreate them in the correct order.
The button
(RemoveAllMarks) removes all split markers as well as the finish line marker.
The three buttons
indicate the way the trajectory is drawn:
(AccelerationMode) (default) draws the The button map using the colors: red for decelerations, blue for accelerations, green when the speed remains roughly constant and white to indicate infrared transponders and the finish line (as shown in figure):
The button (NormalMode) draws the map using a different color for each session or each lap, depending on the active mode:
The button (Elevation) shows altitude differences. Lower areas are drawn with darker colors, and lighter colors are used for higher areas (useful for tracks with altitude differences; this is not meaningful for tracks without any slopes).
The buttons (Sessions and Laps), beside affecting the visualization in NormalMode, allows to choose to show entire sessions or single laps. When 'Sessions' is active, all data from a session is shown, including traits not relative to any lap, for example the pit lane or the paddocks. When 'Laps' is active, only complete laps are shown, if any are present, possibly only those selected in SessionManager. To identify laps, it is necessary to have placed the finish line marker or to have used an infrared transponder.
SESSION MANAGER This region presents two tabs: 'Laps' and 'Sessions'. In the 'Session' tab, all data relative to the sessions are reported: a progressive number, the file containing the data, date and start time of the session, elapsed time, covered distance, number of laps (if an infrared transponder has been used or the finish line marker has been placed on the map), best lap time and the color used in the map to represent the session (the color can be changed by double-clicking on the color itself). Also reported are total time and total covered distance for all the selected session. The leftmost column contains checkboxes to select/deselect sessions. On the bottom there is a button that select/deselect all the loaded sessions.
The 'Laps' summarizes all the loaded lap data (if infrared transponder has been used or finish line marker has been placed on the map).
The first column contains checkboxes to select/deselect the rows, each representing a lap. The selected laps are shown in the other two areas, 3DMap and Graph. The second column identify laps in sessions (for example 4-1 means the first lap in the fourth session). The third column reports the lap time. The best lap is highlighted in bold. The fourth column contains the lap length (covered distance in a lap may vary greatly with different trajectories). The last column indicates the color used to identify the lap in the graphic representations (3DMap and Graph). Each lap color can be changed by double-clicking on the color. The other columns reports the split times, and are present only if splits markers have been placed on the map; the best split time is highlighted in bold. When hovering on a cell containing a time, a tooltip will appear containing the difference to the best time (total or split). Rows can be sorted by clicking on the column headers. The sorting option is shown by ha small arrow in the header, and can be chosen to be: ascending, descending or 'as recorded'. The summary bar on the bottom contains a button to easily select/deselect all rows, and reports the Best time, the Average time, and the Ideal time obtained by adding all the best splits. Times are calculated using only selected laps.
GRAPH AREA This area is dedicated to the analysis of all acquired data, digital as well as analog. In this area all data selected in SessionManager, for all selected laps or sessions, can be charted. Every time a signal is selected, the progress bar on the bottom right shows the loading progress. The area is divided in three columns: the leftmost contains the maximum and minimum value of the selected signal, as well as the choice of the graph style; the center contains the graph, and the rightmost is made up of three tabs ('Axis', 'Values' and 'Derivates') that allow to choose which signals to plot, and the style to use. On the bottom there is also a button bar from where the x axis can be customized, and that contains the buttons that give access to all the analysis functions.
In the button bar, starting from the left we can see:
'View': the user can choose between 'Session' and 'Lap'; when Session is active, the graph shows the selected signal for all the laps in the session (laps are identified by a vertical line marked with an 'F', corresponding to the finish line marker) or the whole covered distance if there are no laps. If no laps have been selected, this is the default modality.
When Lap is active, all the graphs relative to the selected laps are superimposed in the window, starting from the left at each lap start (as shown below). If no lap has been selected, this modality can not be activated, and the program activates the Session modality.
The graphs are drawn in order to fill all the available space on screen, however the visualization can be customized, as explained below. For an explanation of the analysis functionalities, suppose we want to see only GPS speed and RPM for a single lap (3rd lap of the 2nd session). The signal are drawn filling the available space:
The buttons
(Zoom In and Zoom Out) can be used to zoom in and out the graph.
On the right of the bar there is a checkbox called Lock. When activated, prevents zooming on the X axis, leaving only the Y axis to be zoomed in or out. Another important setting is the 'All / Current' drop-down menu, that applies all subsequent actions to all the drawn curves, or only the current curve (the current curve is the one highlighted in the Axis tab; usually is the last drawn curve, and the one which the Y-axis refers to. To make a signal "current", it is sufficient to click on its name in the View tab). Combining the previous settings, different results can be obtained. Here are some examples obtainable from the previous figure:
-- example of zoom out, no lock, applied to all curves: uniform zoom --
-- example of zoom out, with lock, applied to all curves: zoom only on the Y-axis --
-- example of zoom out, with lock, applied only to the current curve: zoom affects only the Y-axis and only the GPS_SPEED curve --
The buttons (Zoom In Mode and Zoom Out Mode) zoom in and out only the portion of the graph selected with the mouse. As an example, zooming in the selected portion
The button (Fit) fits the curves on the screen: useful to reset the graph to initial conditions or, activating the Lock option, to expand on the whole Y-axis the already zoomed-in curves. Applying this option to the last example, we obtain:
(VerticalFit) fits the curves on the Y-axis. The button The button one above the other.
(ParallelFit) separates the curves
(Pan Mode) activates panning. When activated, the graph can be dragged to show the The button desired portion. The buttons up and down.
(MoveLeft, MoveRight, MoveUp and MoveDown) shift the graph to left, right,
The buttons (Refresh, Undo and Redo) have the function to, respectively, redraw the graphs, undo and redo the last action.
The button (Selection Mode) allow to select a portion of the graph (the selection is between two vertical yellow lines). The same portion of trajectory is highlighted in yellow in the 3DMap area (Attention: the highlighted portion will be clearly visible only in the 'Laps' modality, otherwise other laps may cover this portion). The opposite is also true: highlighting a portion of trajectory, the corresponding portion of graph will be selected between the two vertical yellow lines. To cancel any selection, the user can select a zero-size portion of graph, by just clicking on the graph, without dragging.
Though the 'X' drop-down menu the user can select between 'Time' and 'Space': the curves are drawn differently, since the x-axis will represent Time or Space. Here are the curves for GPS_SPEED in two different laps (2-3 and 2-5)
Obviously the two curves do not end at the same point when Time is selected, since usually different laps are covered in different times. It is often more useful to select Space, where all the curves are relative to the covered distance in a lap, so the user can compare what happened in different laps at the same point in the track, in the same curve or a difficult point. To the right there are two boxes where the minimum and maximum values of the X axis can be manually set: the graph will immediately take on the new values. At the left of the Graph area there are quick references: maximum and minimum values and the drawing style are reported. The maximum and minimum values can be manually set to better adjust the vertical zoom factor. Also the drawing style can be quickly changed by clicking on the desired style (normal, bold, dashed…). The style can be also changed by right-clicking on a signal (more on this in the following).
The 'Axis' tab, already mentioned before, contains all the signals that can be drawn in the graph (GPS Speed, RPM, Analog1, etc…). Each signal can be activated by clicking on the corresponding empty selection box. The curve is then drawn, and the Y-axis is labeled with the name and unit of measure of the selected signal. When more than one signal is selected, all of them are drawn, and the last one selected is considered the "current" signal, and is highlighted in blue. The Y-axis is labeled relative to this current signal. To change the current signal, simply click on another signal. The drawing style (solid, dashed, dotted, etc…) can be changed for each curve by right-clicking on the line besides the signal name in the Axis tab.
In the figure above are shown the two curves GPS_SPEED (dashed) and RPM (solid). Current curve is RPM. The color used for every lap is shown in Session Manager
The 'Derivates' tab is similar to the Axis tab, and contains all the drawable derivatives of the signals. Each derivative can be activated by clicking on the selection box. The derivative is then drawn, and the Y-axis reports the name and unit of measure of the selected derivative. When more than one signal is selected, all the curves are drawn. The last one selected is "current", is highlighted in blue and has name and unit of measure reported on the Y-axis. As for the signals, the drawing style can be changed by right-clicking on the lines.
Among the drawable signals the user can also find Gears and GearsRatio. Gears represents the number of the selected gear, the second the gear ration (between pinion revolutions and engine revolutions). Gears is drawn properly only if valid settings have been loaded.
The GearsRatio curve is more "noisy" than the Gears curve. This is because GearsRatio is the result of a direct acquisition, without processing, while Gears is the result of a calculation, so its curve is smoother.
The 'Values' tab contains the value in the graph at the point selected with cursors, each value relative to the different vertical scales. ATTENTION: reported values are not taken on the curves, but are the coordinateof the cursor relative to each signal scale For example, in the figure below we have, from the top, GPS_SPEED, RPM and VEL1 (respectively drawn in solid, dashed and bold). Current signal is RPM.
Clicking in the shown point we can evaluate RPM local minimum. Since the current signal is RPM, in the Values tab the value reported for RPM is correct: the minimum is 5085, consistently with the Y-axis values. The other reported values are not meaningful, since are relative to different Y scales (at the moment not shown: the corresponding signal is not current). In this example, the reported value for GPSspeed is –101.21. It is thevalue of cursor point relative to GPS scale; we need to imagine the graph as it was (deleting RPM and Vel1):
The selected point now has exactly the value reported in the appropriate vertical scale but it is not meaningful since is not on the drawn curve.
If the user had wanted to know the correct value of GPS_SPEED at the same selected time, the point selected by cursor should have been on the GPS_SPEED curve:
In the Values tab the correct value is reported This would be clearly visible if we make the GPS_SPEED curve current: the reported value would be consistent with the Y-axis
SETTINGS MENU As already stated, some telemetry parameters must be set BEFORE the first use using DANAS. It is not necessary to remove DASY from the bike to configure it: it is sufficient to save all the settings on an SD card and the system will load them at the first/next use. The necessary settings are those in the menu 'SettingsÆHardware' (Sampling, IdleTime, AutoStart, Probes), that are integral part of the hardware subsystem. The other parameters (those in 'SettingsÆSoftware'), can be set later, after data acquisition has taken place.
All the parameters can be set through the Settings menu (top left). Each parameter can be saved on the SD card (using the SD Save button) independently. The setting will be read by the system at the next powering up. ATTENTION: the settings can be saved only on SD cards previously initialized using DASY.
Hardware Settings ATTENTION: these parameters MUST be set BEFORE data acquisition. They can not be changed after acquisition since are hardware settings.
Sampling: used to set the sampling time. This is the period between two consecutive samplings. The inverse of sampling time is the sampling frequency. The more frequent the sampling, the higher the precision of data, however a too-high sampling frequency creates very big files and complicates the calculations. Valid values are from 2 to 500 (in hundredths of a second: from 0.02 seconds to 5 seconds; that is from 50 samples per second to 1 sample every 5 seconds).
Idle Time: indicates for how much time the system ignores other infrared signals after successfully detecting one. Used to prevent false triggering when more than one infrared transmitter is present on the pit wall. From 300 to 13000 (in hundredths of a second: from 3 seconds to 130 seconds).
AutoStart: sets which signals can start the sampling process. The sampling can be started when the system detects non-zero speeds (GPS speeds or obtained from a different sensor) or an IR signal or when the dedicated button is pressed.
ATTENTION: NEVER select non-used inputs as autostart. A floating signal may lead to very fast start/stop sequences, and protection may intervene thus locking the system.
Probes: used to set all parameters necessary to the proper working of the system:
The following parameters must be set: o
RPM: Indicates how many pulses are generated by the bike's management system for every engine revolution. Usually must be set to 1 or 2, depending on the bike brand and model, so can be set by trial and error. However, we advise to check the correct setting.
VEL1: Used to set the number of pulses per pinion revolution. If the signal comes from a sensor connected to the pinion, this parameter indicates how many pulses are generated for every pinion revolution. If the sensors measures wheel revolutions instead, the parameters indicates how many pulses are generated for every wheel revolution. There is a strong difference in this parameter for every bike brand and model: can vary between 1 and 40, so we advise against setting by trial and error. The user should check the correct setting. ATTENTION: this signal is often not present when the dashboard is not connected! To find out the correct value, DANAS provides the appropriate tool: AutoCalibration (More in the following).
VEL2: like VEL1, for the second speed.
For all the hardware settings there are two buttons: -
SD Load: loads already saved settings. SD Save: saves settings on an SD card to configure DASY.
Autocalibration As already stated, if the user does not know how to set the number of pulses per revolution (pinion or wheel), DANAS provides an autocalibration tool. This is made possible by the capabilities of DANAS and DASY: this procedure uses DANAS to instruct DASY on how to carry out a measure, then DANAS processes the measure results. The procedure is very simple, and the tools guides the user step by step. For the sake of completeness, here are reported the steps to follow: 1) 2) 3) 4) 5) 6) 7) 8) 9) 10) 11) 12)
Insert the SD card in the PC reader and select the AutoCalibration tool from the Settings menu Set the filename on the SD card (ATTENTION: all data already present will be erased) Extract the SD card (using Windows' "Safely Remove Hardware" procedure) Insert the SD card in DASY and turn on the dashboard, but NOT THE ENGINE The power-on LED indicator on DASY will flash Spin manually the rear wheel for a given number of revolutions (the greater the number, the higher the measure precision; the revolutions must be at least 10) For each wheel revolution, every output pulse make the green LED indicator light up for the duration of the pulse At the end of the chosen number of revolutions, keep the wheel stationary for about 10 seconds: the power-on LED indicator will flash again Extract the SD card from DASY Reinsert the SD card in the PC reader Input the number of revolutions carried out DANAS will calculate the pinion pulse number
Software Settings Used to set all parameters necessary to DANAS proper working, but that can be set after data acquisition. The parameters are: Sensors, Gears, and Derivatives SENSORS
In Vel1 and Vel2 the parameters are Wheel Circumference (must be accurately measured, since this will be used in the final speed calculation, and a small error in this length will lead to large errors in the final results), Pinion Teeth (if the speed is calculated using a sensor connected directly to the pinion, the correct gear ratio is very important to prevent errors in the calculations), and Crown Gear Teeth (as for the pinion, the number is very important; if the sensor is connected directly to the wheel, both this number and the pinion teeth number must be set to 1).
Analog1, Analog2, Front and Rear: the user can set the Label that will be displayed, and the minimum and maximum values on the graph. Analog signals are converted in digital by the system: a voltage between 0 V and 5 V will be transformed in a digital value between 0 and 1023. The parameters represent the actual values to be shown for upper and lower bounds. For example, when measuring a 150-mm potentiometer the minimum value will be 0, the maximum 150. For other kinds of analog inputs the conversion may not be immediate, for example the TPS signal from the management system does not cover the whole range 0-5 V, so the minimum and maximum values must be carefully chosen to make sure the graph is correct. For example: Suppose you want to configure the TPS signal, without knowing the maximum and minimum values corresponding to "closed throttle" and "full throttle". So this procedure can be followed: ƒ Set the minimum and maximum values to 0 and 1023 (theoric full range). ƒ Use DASY to acquire values corresponding to "closed throttle" and "full throttle", for example setting autostart to the rear wheel speed, putting the bike on stand and manually spinning the rear wheel while activating the throttle. ATTENTION: for some bike models, the TPS signal varies when the bike is turned on. We advise to measure TPS with the engine on and closed throttle. If the value is very different from that obtained with the engine off, it will be necessary to carry out the maximum and minimum measures with the engine on, for example while track racing. ƒ The acquired values are between 117 (A) and 780 (B), as shown in the figure below. The graph analysis will be poor given the small covered range.
FIRST acquisition 1023 (max)
600 400 200 117 (A) 0 (min)
The user wants to expand the graph to cover the range 0 (closed throttle) to 100 (full throttle). A transformation is needed to convert the maximum value from 780 to 100, and the minimum value from 117 to 0. With the same transformation the maximum and minimum values to be set will be found. Proceed as follows: DELTA = 1023 * (DESIRED MAXIMUM - DESIRED MINIMUM) / (B – A) therefore: MIN = – A* DELTA /1023 MAX = DELTA + MIN ( attention : MIN will be negative!) For our example:DELTA = 1023 * 100 / (780 – 117) = 154.2964 MIN = – 117 * 154.2964 /1023= –17.64 MAX = 9,053 - 3,75 = 136.65
Setting the calculated values as Min and Max in the TPS settings, the graph will be represented between 0 and 100.
For all the analog signals there is a checkbox marked "Invert". This inverts the read values, thus making DANAS to represent 'MaximumValue – Read Value' instead of 'Read Value'. This can be useful in some cases, for example if we use a sensor to measure fork lengthening, the read value will be the lengthening. But if we are interested in shortening, this is the inverted reading and can be obtained by activating "invert".
Set the gear ratios that identify gears (as in a simple gear counter). These are simply the ratios between Engine Revolutions and Wheel Revolutions for different gears, if these are already known (ATTENTION: to obtain correct measures it is necessary to set the correct pinion teeth number). If the ratios are not known, DANAS offers an utility to calculate the correct settings: FindGears. It is sufficient to select the speed used to sense the rear wheel and press the button "Find gears". For this to work, a session where all gears have been used for at least 10 seconds each, must have been loaded (we advice to create such a session to be used for this calibration). DANAS will then calculate the correct values. ATTENTION: these settings can be saved in the configuration file, using the Save Settings button. So it is not necessary to repeat the configuration for each telemetry used, but only for different bikes.
Derivates
Insert a number representing the smoothing factor when calculating the derivates: the higher the number, the smoother the result. Higher smooth factors are useful to remove noise, but too high smooth factors may introduce time lags and lead to unreliable results. We advise therefore to choose a not too high value.
Load Settings: loads previously saved settings. Useful if the system is used by different persons and/or on different bikes (loads *.cfg files).
Save Settings: saves the settings on a file (*.cfg).
APPENDIX A: RPM, speed and power connections The table contains wire colors valid only for the bikes listed below, and only until the end of 2006. For other connections refer to repair manuals. Aprilia: RSV 1000, MILLE. Honda VTR 1000 SP1/SP2, CBR 600F, CBR900, CBR1100, Hornet600, CBR 600 RR, CBR 900 RR, CBR 954, CBR 1000 R, CBF 600, VFR 800 VTEC Kawasaki: ZX6RR, ZX636, ZX6R, ZX6R, ZX12R, Z1000, Z750, ZX10R, ER6N SUZUKI: Hayabusa, GSXR600, GSX600, GSX750-GSXR750 ,GSXR1000, SV 1000 YAMAHA:FZ 6, FZ 1, YZF-R6, YZF-R1, fazer 600, fazer 1000 N.B.: always verify listed connection; constructor will not assume any responsibilities due to errors in the wire colors listed.
Speed APRILIA RSV 100 Factory 2004 > Grey-White Management system
RSV 1000 2002 Blue-Orange Dashboard rear
Pink-Green
Dashboard rear
CBR 900 RRV 1996
CBR 600 RR 2003-2004
Black-Red Dashboard rear
Pink-Blue Blue connector under air manifold
ZX10R 2004> Blue-Yellow Dashboard rear
ER6N 2006 Pink Dashboard rear
SV 1000 2003 Pink-White Dashboard rear
FZ 6 2004> FZ 1 2006 YZF-R1 2002> YZF-R6 2003 White-Yellow Management system YZF-R1 2004 YZF-R6 2006 White-Yellow 3-pole speed sensor connector
MILLE 2001 Grey-White Management system
CBR 1000R 2004> VFR800 VTEC 2003 VFR 800 2001 Pink Dashboard rear
CBF 600 2004 Pink-Green Main wiring
Z1000 2003> Pink Dashboard rear
Z750 2003> Pink
FZS 600 Fazer 2000>
FZS 1000 Fazer 2001
Pink 3-pole speed sensor connector
White Dashboard rear
White Main wiring
12 V APRILIA RSV 100 Factory 2004 > Green-Red Dashboard rear
RSV 1000 2002 Green Dashboard rear
Black-Brown
CBR 900 RRV 1996 CBR 600 RR 2003-2004 White-Green Dashboard rear
CBR 600 HORNET 2002 Bright Red-Black Dashboard rear
KAWASAKI SUZUKI
Brown-White Orange-Green
Dashboard rear Dashboard rear
GSXR600 / 750 1999 Orange-Red Dashboard rear
FZ 6 2004>
Red-White Main wiring
Red-White Dashboard rear
MILLE 2001 Green Dashboard rear VFR800 VTEC 2003 Brown-Blue Dashboard rear
CBR 1000 R 2004> Brown-White Dashboard rear
FZS 1000 Fazer 2001 Red-Yellow Main wiring
Ground APRILIA
RSV 100 Factory 2004 > Blue Dashboard rear
CBR 900 RR 2002 CBR 954 2002 Green-Black Main wiring
CBF 600 2004 Green Main wiring
KAWASAKI SUZUKI YAMAHA
Black-Yellow Black-White Black-Blue
Dashboard rear Dashboard rear Dashboard rear
YZF-R6 2006 YZF-R1 2002 2004> YZF-R6 2003 Black-White Dashboard rear
Black Main wiring
CBR 600 RR Green Blue connector under air manifold
FZ 1 2006 FZS 600 Fazer 2000> Black Dashboard rear
RPM APRILIA Except:
RSV 100 Factory 2004 > Yellow Dashboard rear
RSV 1000 2002 MILLE 2001 Grey-Purple Dashboard rear
Yellow-Green
CBR 900 RRV 1996 Black-White Dashboard rear
CBR 600 RR 2003-2004 Yellow-Green Blue connector under air manifold
Light Blue Yellow-Blue
GSXR600 / 750 1999 Yellow Dashboard rear
GSX750F 1999 Black-Blue PickUp connector
Yellow-Black
YZF-R6 2006 Yellow-Black Dashboard rear
YZF-R1 2004> Yellow-Black Dashboard rear
FZ 1 2006 White-Black Management system
CBF 600 2004 Yellow-Green Main wiring
SV 1000 2003 White-Grey Management system YZF-R6 2003 Yellow-Black Dashboard rear
FZ 6 2004> Green-Black Management system
Report "DASY & DANAS - I2M"
Copyright © 2021 MOAM.INFO. All rights reserved.
| About Us | Privacy Policy | Terms of Service | Help | Copyright | Contact Us | Cookie Policy


DEVOTION investigates the extremely complex and hierarchical relationships among a loyal group of filmmakers who dedicated up to 30 years making films for one man--Ogawa Shinsuke. These heartbreaking and sometimes funny stories have never been told on film before. Rare footage, stills, and diaries from archives as well as interviews with Oshima Nagisa, Hara Kazuo and Robert Kramer make this historical inquiry visually exciting and valuable.


Live view looking Southeast from Anchorage midtown at Flattop Mountain in the Chugach Mountain Range.
Look at the nice view of the University of Alaska. Museum of the North Construction, at Fairbanks, Alaska.
The majestic Chugach mountain appears in this webcam, a fabolous view of this natural wonder.
Camera looking SouthEast towards entrance to Edna Bay. Entrance Island on right; Limestone Point on left; distance two (plus) miles. Green Island is just to the right of Entrance Is.; distance 5 miles.
This camera is located at the opposite end of Anchorage, at the Potter Marsh Weigh Station. This weigh station is about four miles south of Anchorage on the New Seward highway.
Located on the Sheraton Hotel Anchorage, this camera points east toward the mountains. The inbound car traffic on the left is 5th Avenue and the outbound car traffic on the right is 6th Avenue.
This camera is located on the Denali Towers North office building in Midtown Anchorage and is pointed South-East.
Located on the North-West corner of the Denali Towers office building, this camera shows us a general view of Downtown Anchorage to the north-west.


text:
import sys
import unittest
import json
import requests
import mock

from requests.models import Response

from algoliasearch.exceptions import RequestException, ObjectNotFoundException
from algoliasearch.responses import MultipleResponse
from algoliasearch.search_client import SearchClient
from algoliasearch.search_index import SearchIndex
from tests.helpers.factory import Factory as F
from tests.helpers.misc import Unicode, rule_without_metadata

class TestSearchIndex(unittest.TestCase):
    def setUp(self):
        self.client = F.search_client()
        self.index = F.index(self.client, self._testMethodName)

    def tearDown(self):
        self.client.close()

    def test_tasks(self):
        task_id = self.index.save_object(F.obj()).raw_responses[0]["taskID"]

        task = self.index.get_task(task_id + 1000000)
        self.assertEqual(task["status"], "notPublished")

    def test_indexing(self):
        responses = []

        # adding a object with object id
        obj1 = F.obj()
        responses.append(self.index.save_object(obj1))

        # adding a object w/o object id
        obj2 = F.obj(object_id=False)
        opts = {"autoGenerateObjectIDIfNotExist": True}
        responses.append(self.index.save_object(obj2, opts))

        # adding two objects with object id
        obj3 = F.obj({"_tags": ["algolia"]})
        obj4 = F.obj({"_tags": ["algolia"]})
        responses.append(self.index.save_objects([obj3, obj4]))

        # adding two objects w/o object id
        obj5 = F.obj(object_id=False)
        obj6 = F.obj(object_id=False)
        opts = {"autoGenerateObjectIDIfNotExist": True}
        responses.append(self.index.save_objects([obj5, obj6], opts))

        object1_id = self.get_object_id(responses[0])
        object2_id = self.get_object_id(responses[1])
        object3_id = self.get_object_id(responses[2])
        object4_id = self.get_object_id(responses[2], 1)
        object5_id = self.get_object_id(responses[3])
        object6_id = self.get_object_id(responses[3], 1)

        # adding 1000 objects with object id
        objects = []
        for i in range(1000):
            object_id = i
            objects.append({"objectID": str(object_id), "name": object_id})

        self.index._config.batch_size = 100
        responses.append(self.index.save_objects(objects))

        # waiting for all responses
        MultipleResponse(responses).wait()

        # Check 6 first records with get_object
        self.assertEqual(obj1["name"], self.index.get_object(object1_id)["name"])
        self.assertEqual(obj2["name"], self.index.get_object(object2_id)["name"])
        self.assertEqual(obj3["name"], self.index.get_object(object3_id)["name"])
        self.assertEqual(obj4["name"], self.index.get_object(object4_id)["name"])
        self.assertEqual(obj5["name"], self.index.get_object(object5_id)["name"])
        self.assertEqual(obj6["name"], self.index.get_object(object6_id)["name"])

        # Check 1000 remaining records with get_objects
        results = self.index.get_objects(range(1000))["results"]
        for obj in results:
            self.assertIn(obj, objects)

        self.assertEqual(len(results), len(objects))

        # Browse all records with browse_objects
        results = []
        for obj in self.index.browse_objects():
            results.append(obj)

        for obj in objects:
            self.assertIn(obj, results)

        for obj in [obj1, obj3, obj4]:
            self.assertIn(obj, results)

        self.assertEqual(len(results), 1006)

        responses = []

        # Alter 1 record with partial_update_object
        obj1["name"] = "This is an altered name"
        responses.append(self.index.partial_update_object(obj1))

        # Alter 2 records with partial_update_objects
        obj3["bar"] = 40
        obj4["foo"] = 30
        responses.append(self.index.partial_update_objects([obj3, obj4]))

        MultipleResponse(responses).wait()

        self.assertEqual(self.index.get_object(object1_id), obj1)
        self.assertEqual(self.index.get_object(object3_id), obj3)
        self.assertEqual(self.index.get_object(object4_id), obj4)

        responses = []

        # Delete the 6 first records with delete_object
        responses.append(self.index.delete_object(object1_id))
        responses.append(self.index.delete_object(object2_id))

        responses.append(self.index.delete_by({"tagFilters": ["algolia"]}))
        responses.append(self.index.delete_objects([object5_id, object6_id]))

        # Delete the 1000 remaining records with delete_objects
        responses.append(self.index.clear_objects())

        MultipleResponse(responses).wait()

        objects = [obj for obj in self.index.browse_objects()]

        self.assertEqual(len(objects), 0)

    def test_settings(self):
        self.index.save_object(F.obj()).wait()

        settings = {
            "searchableAttributes": [
                "attribute1",
                "attribute2",
                "attribute3",
                "ordered(attribute4)",
                "unordered(attribute5)",
            ],
            "attributesForFaceting": [
                "attribute1",
                "filterOnly(attribute2)",
                "searchable(attribute3)",
            ],
            "unretrievableAttributes": ["attribute1", "attribute2"],
            "attributesToRetrieve": ["attribute3", "attribute4"],
            "ranking": [
                "asc(attribute1)",
                "desc(attribute2)",
                "attribute",
                "custom",
                "exact",
                "filters",
                "geo",
                "proximity",
                "typo",
                "words",
            ],
            "customRanking": ["asc(attribute1)", "desc(attribute1)"],
            "replicas": [self.index.name + "_replica1", self.index.name + "_replica2"],
            "maxValuesPerFacet": 100,
            "sortFacetValuesBy": "count",
            "attributesToHighlight": ["attribute1", "attribute2"],
            "attributesToSnippet": ["attribute1:10", "attribute2:8"],
            "highlightPreTag": "<strong>",
            "highlightPostTag": "</strong>",
            "snippetEllipsisText": " and so on.",
            "restrictHighlightAndSnippetArrays": True,
            "hitsPerPage": 42,
            "paginationLimitedTo": 43,
            "minWordSizefor1Typo": 2,
            "minWordSizefor2Typos": 6,
            "typoTolerance": "false",
            "allowTyposOnNumericTokens": False,
            "ignorePlurals": True,
            "disableTypoToleranceOnAttributes": ["attribute1", "attribute2"],
            "disableTypoToleranceOnWords": ["word1", "word2"],
            "separatorsToIndex": "()[]",
            "queryType": "prefixNone",
            "removeWordsIfNoResults": "allOptional",
            "advancedSyntax": True,
            "optionalWords": ["word1", "word2"],
            "removeStopWords": True,
            "disablePrefixOnAttributes": ["attribute1", "attribute2"],
            "disableExactOnAttributes": ["attribute1", "attribute2"],
            "exactOnSingleWordQuery": "word",
            "enableRules": False,
            "numericAttributesForFiltering": ["attribute1", "attribute2"],
            "allowCompressionOfIntegerArray": True,
            "attributeForDistinct": "attribute1",
            "distinct": 2,
            "replaceSynonymsInHighlight": False,
            "minProximity": 7,
            "responseFields": ["hits", "hitsPerPage"],
            "maxFacetHits": 100,
            "camelCaseAttributes": ["attribute1", "attribute2"],
            "decompoundedAttributes": {
                "de": ["attribute1", "attribute2"],
                "fi": ["attribute3"],
            },
            "keepDiacriticsOnCharacters": "øé",
            "queryLanguages": ["en", "fr"],
            "alternativesAsExact": ["ignorePlurals"],
            "advancedSyntaxFeatures": ["exactPhrase"],
            "userData": {"customUserData": 42.0},
            "indexLanguages": ["ja"],
        }

        self.index.set_settings(settings).wait()

        # Because the response settings dict contains the extra version key, we
        # also add it to the expected settings dict to prevent the test to fail
        # for a missing key.
        settings["version"] = 2

        # In case something is wrong, we disable the maximum diff length to be
        # able to see which setting is incorrect.
        self.maxDiff = None

        found = self.index.get_settings()

        self.assertEqual(
            self.index.get_settings(),
            Unicode.convert_dict_to_unicode(settings),
        )

        settings["typoTolerance"] = "min"
        settings["ignorePlurals"] = ["en", "fr"]
        settings["removeStopWords"] = ["en", "fr"]
        settings["distinct"] = True

        self.index.set_settings(settings).wait()

        self.assertEqual(
            self.index.get_settings(),
            Unicode.convert_dict_to_unicode(settings),
        )

        # To prevent issues in other test, we reset the maximum diff length to
        # its default value
        self.maxDiff = 80 * 8

    def test_search(self):
        responses = MultipleResponse()

        responses.push(
            self.index.save_objects(
                [
                    {
                        "company": "Algolia",
                        "name": "Julien Lemoine",
                        "objectID": "julien-lemoine",
                    },  # noqa: E501
                    {
                        "company": "Algolia",
                        "name": "Nicolas Dessaigne",
                        "objectID": "nicolas-dessaigne",
                    },  # noqa: E501
                    {"company": "Amazon", "name": "Jeff Bezos"},
                    {"company": "Apple", "name": "Steve Jobs"},
                    {"company": "Apple", "name": "Steve Wozniak"},
                    {"company": "Arista Networks", "name": "Jayshree Ullal"},
                    {"company": "Google", "name": "Larry Page"},
                    {"company": "Google", "name": "Rob Pike"},
                    {"company": "Google", "name": "Serguey Brin"},
                    {"company": "Microsoft", "name": "Bill Gates"},
                    {"company": "SpaceX", "name": "Elon Musk"},
                    {"company": "Tesla", "name": "Elon Musk"},
                    {"company": "Yahoo", "name": "Marissa Mayer"},
                ],
                {"autoGenerateObjectIDIfNotExist": True},
            )
        )

        responses.push(
            self.index.set_settings({"attributesForFaceting": ["searchable(company)"]})
        )

        responses.wait()

        # Perform a search query using search with the query `algolia` and no
        # parameter and check that the number of returned hits is equal to 2
        result = self.index.search("algolia")
        self.assertEqual(result["nbHits"], 2)
        self.assertEqual(
            SearchIndex.get_object_position(result, "nicolas-dessaigne"), 0
        )
        self.assertEqual(SearchIndex.get_object_position(result, "julien-lemoine"), 1)

        self.assertEqual(SearchIndex.get_object_position(result, ""), -1)

        # Call find_object with the following parameters and check that
        # no object is found
        with self.assertRaises(ObjectNotFoundException):
            self.index.find_object(lambda _: False)

        # Call find_object with the following parameters and check that
        # the first object is returned with a `position=0` and `page=0`
        found = self.index.find_object(lambda _: True)
        self.assertEqual(found["position"], 0)
        self.assertEqual(found["page"], 0)

        def callback(obj):
            # type: (dict) -> bool
            return obj.get("company") == "Apple"

        # Call find_object with the following parameters and check that
        # no object is found
        with self.assertRaises(ObjectNotFoundException):
            self.index.find_object(callback, {"query": "algolia"})

        # Call find_object with the following parameters and check that
        # no object is found
        with self.assertRaises(ObjectNotFoundException):
            self.index.find_object(
                callback, {"query": "", "paginate": False, "hitsPerPage": 5}
            )

        # Call find_object with the following parameters and check that
        # the first object is returned with a `position=0` and `page=2`
        found = self.index.find_object(
            callback, {"query": "", "paginate": True, "hitsPerPage": 5}
        )

        self.assertEqual(found["position"], 0)
        self.assertEqual(found["page"], 2)

        # Perform a search using search with the query `elon` and the
        # following parameter and check that the queryID field from
        # the response is not empty
        result = self.index.search("elon", {"clickAnalytics": True})
        self.assertIn("queryID", result)

        # Perform a faceted search using search with the query `elon` and the
        # following parameters and check that the number of returned hits is
        # equal to 1
        result = self.index.search(
            "elon", {"facets": "*", "facetFilters": "company:tesla"}
        )
        self.assertEqual(result["nbHits"], 1)

        # Perform a filtered search using search with the query `elon` and the
        # following parameters and check that the number of returned hits is
        # equal to 2
        result = self.index.search(
            "elon", {"facets": "*", "filters": "(company:tesla OR company:spacex)"}
        )

        self.assertEqual(result["nbHits"], 2)

        result = self.index.search_for_facet_values("company", "a")["facetHits"]

        values = list(map(lambda facet: facet["value"], result))

        self.assertIn("Algolia", values)
        self.assertIn("Amazon", values)
        self.assertIn("Apple", values)
        self.assertIn("Arista Networks", values)

    def test_synonyms(self):
        responses = MultipleResponse()

        responses.push(
            self.index.save_objects(
                [
                    {"console": "Sony PlayStation <PLAYSTATIONVERSION>"},
                    {"console": "Nintendo Switch"},
                    {"console": "Nintendo Wii U"},
                    {"console": "Nintendo Game Boy Advance"},
                    {"console": "Microsoft Xbox"},
                    {"console": "Microsoft Xbox 360"},
                    {"console": "Microsoft Xbox One"},
                ],
                {"autoGenerateObjectIDIfNotExist": True},
            )
        )

        responses.push(
            self.index.save_synonym(
                F.synonym(
                    {"synonyms": ["gba", "gameboy advance", "game boy advance"]}, "gba"
                )
            )
        )

        synonym1 = {
            "objectID": "wii_to_wii_u",
            "type": "onewaysynonym",
            "input": "wii",
            "synonyms": ["wii U"],
        }

        synonym2 = {
            "objectID": "playstation_version_placeholder",
            "type": "placeholder",
            "placeholder": "<PLAYSTATIONVERSION>",
            "replacements": ["1", "One", "2", "3", "4", "4 Pro"],
        }

        synonym3 = {
            "objectID": "ps4",
            "type": "altcorrection1",
            "word": "ps4",
            "corrections": ["playstation4"],
        }

        synonym4 = {
            "objectID": "psone",
            "type": "altcorrection2",
            "word": "psone",
            "corrections": ["playstationone"],
        }

        responses.push(
            self.index.save_synonyms([synonym1, synonym2, synonym3, synonym4])
        )

        responses.wait()

        self.assertEqual(self.index.get_synonym(synonym1["objectID"]), synonym1)
        self.assertEqual(self.index.get_synonym(synonym2["objectID"]), synonym2)
        self.assertEqual(self.index.get_synonym(synonym3["objectID"]), synonym3)
        self.assertEqual(self.index.get_synonym(synonym4["objectID"]), synonym4)

        self.assertEqual(self.index.search_synonyms("")["nbHits"], 5)

        # Browse all records with browse_objects
        results = []
        for obj in self.index.browse_synonyms():
            results.append(obj)

        synonyms = [synonym1, synonym2, synonym3, synonym4]

        for synonym in synonyms:
            self.assertIn(synonym, results)

        self.index.delete_synonym("gba").wait()

        # Try to get the synonym with getSynonym with objectID `gba and c
        # heck that the synonym does not exist anymore
        with self.assertRaises(RequestException) as _:
            self.index.get_synonym("gba")

        # Clear all the synonyms using clear_synonyms
        self.index.clear_synonyms().wait()

        # Perform a synonym search using searchSynonyms with an empty query
        # and check that the number of returned synonyms is equal to 0
        self.assertEqual(self.index.search_synonyms("")["nbHits"], 0)

    def test_browse_rules(self):
        def side_effect(req, **kwargs):
            hits = [{"objectID": i, "_highlightResult": None} for i in range(0, 1000)]
            page = json.loads(req.body)["page"]

            if page == 3:
                hits = hits[0:800]

            response = Response()
            response.status_code = 200
            response._content = str.encode(
                json.dumps(
                    {
                        "hits": hits,
                        "nbHits": 3800,
                        "page": page,
                        "nbPages": 3,
                    }
                )
            )

            return response

        client = SearchClient.create("foo", "bar")
        client._transporter._requester._session = requests.Session()
        client._transporter._requester._session.send = mock.MagicMock(name="send")
        client._transporter._requester._session.send.side_effect = side_effect
        index = F.index(client, "test")

        rules = index.browse_rules()

        len_rules = len(list(rules))

        self.assertEqual(len_rules, 3800)

    def test_rules(self):
        responses = MultipleResponse()

        responses.push(
            self.index.save_objects(
                [
                    {"objectID": "iphone_7", "brand": "Apple", "model": "7"},
                    {"objectID": "iphone_8", "brand": "Apple", "model": "8"},
                    {"objectID": "iphone_x", "brand": "Apple", "model": "X"},
                    {"objectID": "one_plus_one", "brand": "OnePlus", "model": "One"},
                    {"objectID": "one_plus_two", "brand": "OnePlus", "model": "Two"},
                ]
            )
        )

        responses.push(
            self.index.set_settings({"attributesForFaceting": ["brand", "model"]})
        )

        rule1 = {
            "objectID": "brand_automatic_faceting",
            "enabled": False,
            "condition": {"anchoring": "is", "pattern": "{facet:brand}"},
            "consequence": {
                "params": {
                    "automaticFacetFilters": [
                        {"facet": "brand", "disjunctive": True, "score": 42},
                    ]
                }
            },
            "validity": [
                {"from": 1532439300, "until": 1532525700},
                {"from": 1532612100, "until": 1532698500},
            ],
            "description": "Automatic apply the faceting on `brand` if a",
        }

        responses.push(self.index.save_rule(rule1))

        rule2 = {
            "objectID": "query_edits",
            "conditions": [
                {"anchoring": "is", "pattern": "mobile phone", "alternatives": True}
            ],
            "consequence": {
                "params": {
                    "query": {
                        "edits": [
                            {"type": "remove", "delete": "mobile"},
                            {"type": "replace", "delete": "phone", "insert": "iphone"},
                        ]
                    }
                }
            },
        }

        rule3 = {
            "objectID": "query_promo",
            "consequence": {"params": {"filters": "brand:OnePlus"}},
        }

        rule4 = {
            "objectID": "query_promo_only_summer",
            "condition": {"context": "summer"},
            "consequence": {"params": {"filters": "model:One"}},
        }

        responses.push(self.index.save_rules([rule2, rule3, rule4]))

        responses.wait()

        # Should be only the One Plus model One
        self.assertEqual(
            self.index.search("", {"ruleContexts": ["summer"]})["nbHits"], 1
        )

        self.assertEqual(
            rule_without_metadata(self.index.get_rule(rule1["objectID"])), rule1
        )

        self.assertEqual(
            rule_without_metadata(self.index.get_rule(rule2["objectID"])), rule2
        )

        self.assertEqual(
            rule_without_metadata(self.index.get_rule(rule3["objectID"])), rule3
        )

        self.assertEqual(
            rule_without_metadata(self.index.get_rule(rule4["objectID"])), rule4
        )

        self.assertEqual(self.index.search_rules("")["nbHits"], 4)

        # Browse all records with browse_rules
        results = []
        for obj in self.index.browse_rules():
            if isinstance(obj, dict):
                results.append(rule_without_metadata(obj))

        rules = [rule1, rule2, rule3, rule4]

        for rule in rules:
            self.assertIn(rule, results)

        self.index.delete_rule(rule1["objectID"]).wait()

        # Try to get the first rule with get_rule and check
        # that the rule does not exist anymore
        with self.assertRaises(RequestException) as _:
            self.index.get_rule(rule1["objectID"])

        # Clear all the rules using clear_rules
        self.index.clear_rules().wait()

        # Perform a rule search using search_rule with an empty query
        # and check that the number of returned nbHits is equal to 0
        self.assertEqual(self.index.search_rules("")["nbHits"], 0)

    def test_batching(self):
        responses = MultipleResponse()

        responses.push(
            self.index.save_objects(
                [
                    {"objectID": "one", "key": "value"},
                    {"objectID": "two", "key": "value"},
                    {"objectID": "three", "key": "value"},
                    {"objectID": "four", "key": "value"},
                    {"objectID": "five", "key": "value"},
                ]
            )
        )

        responses.push(
            self.index.batch(
                [
                    {
                        "action": "addObject",
                        "body": {"objectID": "zero", "key": "value"},
                    },
                    {"action": "updateObject", "body": {"objectID": "one", "k": "v"}},
                    {
                        "action": "partialUpdateObject",
                        "body": {"objectID": "two", "k": "v"},
                    },
                    {
                        "action": "partialUpdateObject",
                        "body": {"objectID": "two_bis", "key": "value"},
                    },
                    {
                        "action": "partialUpdateObjectNoCreate",
                        "body": {"objectID": "three", "k": "v"},
                    },
                    {"action": "deleteObject", "body": {"objectID": "four"}},
                ]
            )
        )

        responses.wait()

        objects = [
            {"objectID": "zero", "key": "value"},
            {"objectID": "one", "k": "v"},
            {"objectID": "two", "key": "value", "k": "v"},
            {"objectID": "two_bis", "key": "value"},
            {"objectID": "three", "key": "value", "k": "v"},
            {"objectID": "five", "key": "value"},
        ]

        results = [obj for obj in self.index.browse_objects()]

        for obj in objects:
            self.assertIn(obj, results)

    def test_replacing(self):
        responses = MultipleResponse()
        responses.push(self.index.save_object({"objectID": "one"}))
        responses.push(self.index.save_rule(F.rule(object_id="one")))

        responses.push(
            self.index.save_synonym(
                {"objectID": "one", "type": "synonym", "synonyms": ["one", "two"]}
            )
        )

        responses.wait()

        responses.push(self.index.replace_all_objects([{"objectID": "two"}]))
        responses.push(
            self.index.replace_all_rules(
                [
                    {
                        "objectID": "two",
                        "condition": {"anchoring": "is", "pattern": "pattern"},
                        "consequence": {
                            "params": {
                                "query": {
                                    "edits": [{"type": "remove", "delete": "pattern"}]
                                }
                            }
                        },
                    }
                ]
            )
        )

        responses.push(
            self.index.replace_all_synonyms(
                [{"objectID": "two", "type": "synonym", "synonyms": ["one", "two"]}]
            )
        )

        responses.wait()

        # Check that record with objectID=`one` does not exist
        with self.assertRaises(RequestException) as _:
            self.index.get_object("one")

        # Check that record with objectID=`two` does exist
        self.assertEqual(self.index.get_object("two")["objectID"], "two")

        # Check that rule with objectID=`one` does not exist
        with self.assertRaises(RequestException) as _:
            self.index.get_rule("one")

        # Check that rule with objectID=`two` does exist
        self.assertEqual(self.index.get_rule("two")["objectID"], "two")

        # Check that synonym with objectID=`one` does not exist
        with self.assertRaises(RequestException) as _:
            self.index.get_synonym("one")

        # Check that synonym with objectID="two" does exist using getSynonym
        self.assertEqual(self.index.get_synonym("two")["objectID"], "two")

    def test_safe_replacing(self):

        # Adds dummy object
        self.index.save_object(F.obj()).wait()

        # Calls replace all objects with an object without
        # object id, and with the safe parameter
        self.index.replace_all_objects(
            [{"name": "two"}], {"autoGenerateObjectIDIfNotExist": True, "safe": True}
        )

        response = self.index.search("")
        self.assertEqual(response["nbHits"], 1)
        hit = response["hits"][0]
        self.assertEqual(hit["name"], "two")
        self.assertIn("objectID", hit)
        self.assertIn("_highlightResult", hit)

    def test_exists(self):
        self.assertFalse(self.index.exists())
        self.index.save_object(F.obj()).wait()
        self.assertTrue(self.index.exists())
        self.index.delete().wait()
        self.assertFalse(self.index.exists())

    def test_url_encoding(self):
        objects = [
            # unicode
            "中文",
            # bytestring
            "celery-task-meta-c4f1201f-eb7b-41d5-9318-a75a8cfbdaa0",
            b"celery-task-meta-c4f1201f-eb7b-41d5-9318-a75a8cfbdaa0",
            # misc
            "àlgol?a",
            b"\xe4\xb8\xad\xe6\x96\x87",
            "$^^`",
        ]

        if sys.version_info >= (3, 0):
            objects.append("中文".encode("utf-8"))

        self.index.save_objects(
            [{"objectID": object_id} for object_id in objects]
        ).wait()

        for obj in objects:
            self.index.get_object(obj)

    def get_object_id(self, indexing_response, index=0):
        return indexing_response.raw_responses[0]["objectIDs"][index]

redpajama_set_name: RedPajamaGithub