| """ |
| Copyright (c) 2019, OptoFidelity OY |
| |
| Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: |
| |
| 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. |
| 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. |
| 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the OptoFidelity OY. |
| 4. Neither the name of the OptoFidelity OY nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. |
| |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY |
| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY |
| DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| """ |
| |
| import traceback |
| import json |
| |
| import cherrypy |
| from cherrypy import HTTPError |
| from genshi.template import MarkupTemplate |
| |
| from .base_page import BasePage |
| from .measurementdb import get_database, Setting |
| import TPPTAnalysisSW.test_session as test_session |
| import TPPTAnalysisSW.imagefactory as imagefactory |
| from .settings import settings, setting_categories, loadSettings |
| from .info.version import Version |
| import TPPTAnalysisSW.progressstatus as progressstatus |
| import TPPTAnalysisSW.test_refs as test_refs |
| |
| |
| #Settings controller for settings-view |
| class SettingsController(BasePage): |
| |
| SAVEPATH = "" |
| |
| def GET(self, *args, **kwargs): |
| |
| if "event" in kwargs: |
| cherrypy.response.headers["Content-Type"] = "text/event-stream" |
| cherrypy.response.headers["Transfer-Encoding"] = "identity" |
| return "data: " + str(progressstatus.progress) + "\ndata:\nretry:500\n\n" |
| |
| dbsession = get_database().session() |
| with open("templates/settings.html") as f: |
| |
| tmpl = MarkupTemplate(f) |
| settings = dbsession.query(Setting).all() |
| groups = self.settings_by_group(settings) |
| stream = tmpl.generate(groups=groups, version=Version) |
| |
| return stream.render('xhtml') |
| |
| def POST(self, *args, **kwargs): |
| |
| dbsession = get_database().session() |
| data = json.loads(kwargs['params']) |
| |
| for i in data: |
| setting = dbsession.query(Setting).filter(Setting.id == i['id']).first() |
| try: |
| strvalue = i['value'] |
| strvalue = strvalue.replace(',', '.') # Allow comma decimal separator |
| setting.value = float(strvalue) |
| except ValueError: |
| print(traceback.format_exc()) |
| dbsession.rollback() |
| raise HTTPError("500", "Float value required for %s" % setting.desc) |
| |
| dbsession.commit() |
| loadSettings(dbsession) # from settings.py |
| |
| # clear cache |
| test_refs.testclass_refs.clear() |
| imagefactory.ImageFactory.delete_all_images() |
| |
| if kwargs['mode'] == "recalculate": |
| |
| testsessions = get_database().get_test_sessions() |
| length = len(testsessions) |
| |
| for idx, ts in enumerate(testsessions): |
| test_session.TestSession.eval_tests_results(dbsession, ts.id) |
| if idx == 0: |
| progressstatus.progress = 0 |
| else: |
| progressstatus.progress = round(idx / float(length), 2) |
| |
| progressstatus.progress = 0 |
| |
| return "Settings saved and analyses recalculated." |
| |
| testsessions = get_database().get_test_sessions() |
| |
| for ts in testsessions: |
| test_session.TestSession.eval_tests_results(dbsession, ts.id, recalculate=False) |
| |
| return "Settings saved but analyses were not recalculated." |
| |
| def settings_by_group(self, settings): |
| # Copy settings to safety |
| settings = list(settings) |
| groups, groups_settings = self.parse_groups() |
| |
| # Replace setting_id with given setting |
| for group_settings in groups_settings: |
| for i, setting_id in enumerate(group_settings): |
| setting = [s for s in settings if s.id == setting_id] |
| if len(setting) == 0: |
| raise HTTPError(status="500", message="Internal error: setting %s not found in database" % setting) |
| else: |
| settings.remove(setting[0]) |
| group_settings[i] = setting[0] |
| |
| if len(settings) > 0: |
| # There are non-categorized settings |
| groups.append(None) |
| groups_settings.append(settings) |
| |
| # Note: this will break if some of the settings given in settings_categories |
| # is not found in the database. This should be rare condition, as missing |
| # settings are inserted in the startup sequence |
| |
| return zip(groups, groups_settings) |
| |
| def parse_groups(self): |
| """ |
| Parses the group to list of categories. Creates separate categories |
| for settings that are in multiple categories |
| """ |
| |
| settings_dict = {} |
| |
| # Create settings list (reverse: setting_id -> categories) |
| # Note: generated lists are equal if they are included in the same categories |
| for name, settings_list in setting_categories.items(): |
| for setting_id in settings_list: |
| if setting_id in settings_dict: |
| settings_dict[setting_id].append(name) |
| else: |
| settings_dict[setting_id] = [name] |
| |
| # List of different categories |
| groups = [] |
| # Settings in each category |
| groups_settings = [] |
| |
| for setting_id, groups_list in settings_dict.items(): |
| if groups_list in groups: |
| # Append setting to the specific group |
| groups_settings[groups.index(groups_list)].append(setting_id) |
| else: |
| # Create a new group in list and add the settings to it |
| # order groups by number of categories in group and alphabetically |
| for index_to in range(len(groups)): |
| if len(groups[index_to]) < len(groups_list): |
| continue |
| elif (len(groups[index_to]) > len(groups_list) or |
| groups[index_to][0] > groups_list[0]): |
| groups.insert(index_to, groups_list) |
| groups_settings.insert(index_to, [setting_id]) |
| break |
| else: |
| # Append |
| groups.append(groups_list) |
| groups_settings.append([setting_id]) |
| |
| return (groups, groups_settings) |
| |
| exposed = True |