import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import ru.it.metasonic.ruspost.infopoint.utils.BOHelper; import ru.lbpm.metasonic.businessobjects.DbHelper; import com.jcom1.api.constants.Constants.Storage.BusinessObject20; import com.jcom1.api.dto.interfaces.IStorageInstanceBean; import com.jcom1.api.dto.interfaces.ISubjectInstanceBean; import com.jcom1.api.dto.interfaces.storages.IStorageInstanceItemBeanReducedToId; import com.jcom1.api.interfaces.IAuthorizationAdministrationApi; import com.jcom1.api.interfaces.IAuthorizationApi; import com.jcom1.api.interfaces.IBo20AccessApi; import com.jcom1.api.interfaces.ICommonApi; import com.jcom1.api.util.IViewStorageInstanceItemPair; import com.jcom1.api.util.Pair; import com.jcom1.runtime.refinement.AbstractRefinement; import com.jcom1.runtime.refinement.FunctionStateRequest; import com.jcom1.runtime.refinement.FunctionStateResponse; import com.jcom1.runtime.refinement.RefinementGenerator; import com.jcom1.runtime.refinement.SendStateRequest; import com.jcom1.runtime.refinement.SendStateResponse; import de.metasonic.businessobjects.model.interfaces.IView; import de.metasonic.refinement.global.api.ApiUtils; @RefinementGenerator(id = "InternalSubjectDescription_YkfkUSyFEeaLN6UD03S8mg") public class Регистратор_событийRefinement extends AbstractRefinement { @Autowired ICommonApi commonApi; @Autowired IBo20AccessApi accessApi; @Autowired IAuthorizationApi authApi; @Autowired IAuthorizationAdministrationApi administrationApi; final String responsibleSubjectDescId = "InternalSubjectDescription_xRtowSvvEea91xRuMXueEA"; private final String DB_URL = "jdbc:hsqldb:hsql://localhost/jcom1"; private final String DB_USER = "sa"; private final String DB_PSW = ""; private final String UFPS_INDEX = "UFPS_INDEX"; private final String UFPS_NAME = "UFPS_NAME"; private final String POSTAMT_INDEX = "POSTAMT_INDEX"; private final String POSTAMT_NAME = "POSTAMT_NAME"; private final String UM_GROUP = "UM_GROUP"; private final String UM_USER = "UM_USER"; private final String UM_GROUP_AS_INDEX = "INDX"; private final String UM_GROUP_AS_ROLE = "ROLE"; private final String ID_AS_IP_ID = "IP_ID"; private final String OPERATOR_IP = "OPERATOR-IP"; private final String ACTIVE_TASK_NUMBER = "ACTIVE_TASK_NUMBER"; private int operatorIpId; /** * @generated */ private final static Log log = LogFactory .getLog("com.jcom1.refinement.p01__регистрация_событий.регистратор_событийrefinement"); /** * This function provides the data to send in the named state. TransitionID * SendTransitionDescription_YEfBoU5xEeaKw8bSpzxULQ State: Отправить * инцидент в работу MessageType: Инцидент TransitionType SEND Destination * Subject 02. Обработка инцидента * * @return // return the id of the transition to follow or null to stay in * this state e.g. // return new * SendStateResponse("transitionXXXXXXXX"); * @generated */ @RefinementGenerator(id = "SendStateDescription_R7itcU5xEeaKw8bSpzxULQ") public SendStateResponse sendStateОтправить_инцидент_в_работу( SendStateRequest sendStateRequest) { de.metasonic.reftmpl.bo20automaticsend.runtime.Bo20AutomaticSendRuntime refinementRuntime = new de.metasonic.reftmpl.bo20automaticsend.runtime.Bo20AutomaticSendRuntime(); de.metasonic.support.context.ApplicationContextProvider.getInstance() .getApplicationContext().getAutowireCapableBeanFactory() .autowireBean(refinementRuntime); refinementRuntime .setStateConfig(DATA_SendStateDescription_R7itcU5xEeaKw8bSpzxULQ); try { return (SendStateResponse) refinementRuntime.execute( getSubjectInstance(), getSubjectDescription(), getClass() .getClassLoader()); } catch (Exception ex) { throw new RuntimeException(ex); } } /** * This function provides the data to send in the named state. TransitionID * SendTransitionDescription_d6CssCyFEeaLN6UD03S8mg State: Отправка * замечания в работу MessageType: Замечание TransitionType SEND Destination * Subject 03. Обработка замечаний * * @return // return the id of the transition to follow or null to stay in * this state e.g. // return new * SendStateResponse("transitionXXXXXXXX"); * @generated */ @RefinementGenerator(id = "SendStateDescription_d6JaYCyFEeaLN6UD03S8mg") public SendStateResponse sendStateОтправка_замечания_в_работу( SendStateRequest sendStateRequest) { de.metasonic.reftmpl.bo20automaticsend.runtime.Bo20AutomaticSendRuntime refinementRuntime = new de.metasonic.reftmpl.bo20automaticsend.runtime.Bo20AutomaticSendRuntime(); de.metasonic.support.context.ApplicationContextProvider.getInstance() .getApplicationContext().getAutowireCapableBeanFactory() .autowireBean(refinementRuntime); refinementRuntime .setStateConfig(DATA_SendStateDescription_d6JaYCyFEeaLN6UD03S8mg); try { return (SendStateResponse) refinementRuntime.execute( getSubjectInstance(), getSubjectDescription(), getClass() .getClassLoader()); } catch (Exception ex) { throw new RuntimeException(ex); } } /** * @generated */ private static final String DATA_SendStateDescription_d6JaYCyFEeaLN6UD03S8mg = "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48Y29uZmlndXJhdGlvbj48U1RBVEVfSUQgdmFsdWU9IlNlbmRTdGF0ZURlc2NyaXB0aW9uX2Q2SmFZQ3lGRWVhTE42VUQwM1M4bWciLz48Ym8yMF9maWVsZC5ibyB2YWx1ZT0icnUuaXQubWV0YXNvbmljLnJ1c3Bvc3QuaW5mb3BvaW50LmRhdGEuZXZlbnRjYXJkLkV2ZW50Q2FyZERpc3BsYXlWaWV3Ii8+PGJvMjBfZmllbGQuZmllbGQgdmFsdWU9InBvc3RhbXROYW1lIi8+PGJvMjBfZmllbGQudHlwZSB2YWx1ZT0iU1RSSU5HIi8+PHVzZXJPckdyb3VwX2ZpZWxkLnZhbHVlIHZhbHVlPSJncm91cF9uYW1lIi8+PGJvMjBfZmllbGQubW9kZSB2YWx1ZT0ic2luZ2xlIi8+PGJvMjBfZmllbGQuc3RvcmFnZSB2YWx1ZT0iQk9TdG9yYWdlRGVzY3JpcHRpb25fMUhwZzBEZV9FZWFRc3BLQ05RT1NuQSIvPjwvY29uZmlndXJhdGlvbj4="; /** * @generated */ private static final String DATA_SendStateDescription_R7itcU5xEeaKw8bSpzxULQ = "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48Y29uZmlndXJhdGlvbj48U1RBVEVfSUQgdmFsdWU9IlNlbmRTdGF0ZURlc2NyaXB0aW9uX1I3aXRjVTV4RWVhS3c4YlNwenhVTFEiLz48Ym8yMF9maWVsZC5ibyB2YWx1ZT0icnUuaXQubWV0YXNvbmljLnJ1c3Bvc3QuaW5mb3BvaW50LmRhdGEuZXZlbnRjYXJkLkV2ZW50Q2FyZERpc3BsYXlWaWV3Ii8+PGJvMjBfZmllbGQuZmllbGQgdmFsdWU9InBvc3RhbXROYW1lIi8+PGJvMjBfZmllbGQudHlwZSB2YWx1ZT0iU1RSSU5HIi8+PHVzZXJPckdyb3VwX2ZpZWxkLnZhbHVlIHZhbHVlPSJncm91cF9uYW1lIi8+PGJvMjBfZmllbGQubW9kZSB2YWx1ZT0ic2luZ2xlIi8+PGJvMjBfZmllbGQuc3RvcmFnZSB2YWx1ZT0iQk9TdG9yYWdlRGVzY3JpcHRpb25fMUhwZzBEZV9FZWFRc3BLQ05RT1NuQSIvPjwvY29uZmlndXJhdGlvbj4="; /** * @generated */ private static final String DATA_FunctionStateDescription_H2hzQV77EeaP64PmrlFw2w = "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48Y29uZmlndXJhdGlvbj48U1RBVEVfSUQgdmFsdWU9IkZ1bmN0aW9uU3RhdGVEZXNjcmlwdGlvbl9IMmh6UVY3N0VlYVA2NFBtcmxGdzJ3Ii8+PGJvMjBfZmllbGQuYm8gdmFsdWU9InJ1Lml0Lm1ldGFzb25pYy5ydXNwb3N0LmluZm9wb2ludC5kYXRhLmV2ZW50Y2FyZC5FdmVudENhcmRJbml0VmlldyIvPjxzdG9yYWdlLnZhbHVlIHZhbHVlPSJCT1N0b3JhZ2VEZXNjcmlwdGlvbl8xSHBnMERlX0VlYVFzcEtDTlFPU25BIi8+PGJvMjBfZmllbGQudHlwZS4xIHZhbHVlPSJFTlVNIi8+PGJvMjBfZmllbGQudmFsdWUuMSB2YWx1ZT0ibmV3SW5jaWRlbnQiLz48Ym8yMF9maWVsZC5tb2RlIHZhbHVlPSJjaGVjayIvPjxibzIwX2ZpZWxkLmZpZWxkLjEgdmFsdWU9InN0YXR1cyIvPjxibzIwX2ZpZWxkLnN0b3JhZ2UgdmFsdWU9IkJPU3RvcmFnZURlc2NyaXB0aW9uXzFIcGcwRGVfRWVhUXNwS0NOUU9TbkEiLz48L2NvbmZpZ3VyYXRpb24+"; /** * @generated */ private static final String DATA_FunctionStateDescription___fMQV7_EeaP64PmrlFw2w = "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48Y29uZmlndXJhdGlvbj48U1RBVEVfSUQgdmFsdWU9IkZ1bmN0aW9uU3RhdGVEZXNjcmlwdGlvbl9fX2ZNUVY3X0VlYVA2NFBtcmxGdzJ3Ii8+PGJvMjBfZmllbGQuYm8gdmFsdWU9InJ1Lml0Lm1ldGFzb25pYy5ydXNwb3N0LmluZm9wb2ludC5kYXRhLmV2ZW50Y2FyZC5FdmVudENhcmREaXNwbGF5UmVtYXJrVmlldyIvPjxzdG9yYWdlLnZhbHVlIHZhbHVlPSJCT1N0b3JhZ2VEZXNjcmlwdGlvbl8xSHBnMERlX0VlYVFzcEtDTlFPU25BIi8+PGJvMjBfZmllbGQudHlwZS4xIHZhbHVlPSJFTlVNIi8+PGJvMjBfZmllbGQudmFsdWUuMSB2YWx1ZT0icmVtYXJrSXNSZWdpc3RlcmVkIi8+PGJvMjBfZmllbGQubW9kZSB2YWx1ZT0iY2hlY2siLz48Ym8yMF9maWVsZC5maWVsZC4xIHZhbHVlPSJzdGF0dXMiLz48Ym8yMF9maWVsZC5zdG9yYWdlIHZhbHVlPSJCT1N0b3JhZ2VEZXNjcmlwdGlvbl8xSHBnMERlX0VlYVFzcEtDTlFPU25BIi8+PC9jb25maWd1cmF0aW9uPg=="; /** * This method is called when the named function state is reached State: * STATUS: Установить статус: Новое событие StateType: FUNCTION * * Return values "FunctionTransitionDescription_NkQyIV77EeaP64PmrlFw2w" when * result is "" to go to state Запуск контроля срока обработки * * @return return the id of the transition to follow e.g. // return new * FunctionStateResponse("transitionXXXXXXXX"); * @generated */ @RefinementGenerator(id = "FunctionStateDescription_H2hzQV77EeaP64PmrlFw2w") public FunctionStateResponse functionSTATUS__Установить_статус__Новое_событие( FunctionStateRequest functionStateRequest) { de.metasonic.reftmpl.fieldvaluesetter.runtime.RefinementTemplateRuntime refinementRuntime = new de.metasonic.reftmpl.fieldvaluesetter.runtime.RefinementTemplateRuntime(); de.metasonic.support.context.ApplicationContextProvider.getInstance() .getApplicationContext().getAutowireCapableBeanFactory() .autowireBean(refinementRuntime); refinementRuntime .setStateConfig(DATA_FunctionStateDescription_H2hzQV77EeaP64PmrlFw2w); try { return (FunctionStateResponse) refinementRuntime.execute( getSubjectInstance(), getSubjectDescription(), getClass() .getClassLoader()); } catch (Exception ex) { throw new RuntimeException(ex); } } /** * This method is called when the named function state is reached State: * STATUS: Установить статус: Инцидент зарегистрирован StateType: FUNCTION * * Return values "FunctionTransitionDescription_cxH2gV7xEeaP64PmrlFw2w" when * result is "" to go to state Событие определено как инцидент * * @return return the id of the transition to follow e.g. // return new * FunctionStateResponse("transitionXXXXXXXX"); * @generated */ @RefinementGenerator(id = "FunctionStateDescription_UebAgV7xEeaP64PmrlFw2w") public FunctionStateResponse functionSTATUS__Установить_статус__Инцидент_зарегистрирован( FunctionStateRequest functionStateRequest) { de.metasonic.reftmpl.fieldvaluesetter.runtime.RefinementTemplateRuntime refinementRuntime = new de.metasonic.reftmpl.fieldvaluesetter.runtime.RefinementTemplateRuntime(); de.metasonic.support.context.ApplicationContextProvider.getInstance() .getApplicationContext().getAutowireCapableBeanFactory() .autowireBean(refinementRuntime); refinementRuntime .setStateConfig(DATA_FunctionStateDescription_UebAgV7xEeaP64PmrlFw2w); try { return (FunctionStateResponse) refinementRuntime.execute( getSubjectInstance(), getSubjectDescription(), getClass() .getClassLoader()); } catch (Exception ex) { throw new RuntimeException(ex); } } /** * This method is called when the named function state is reached State: * STATUS: Установить статус: Замечание зарегистрировано StateType: FUNCTION * * Return values "FunctionTransitionDescription_fJoUEV8AEeaP64PmrlFw2w" when * result is "" to go to state Событие определено как замечание * * @return return the id of the transition to follow e.g. // return new * FunctionStateResponse("transitionXXXXXXXX"); * @generated */ @RefinementGenerator(id = "FunctionStateDescription___fMQV7_EeaP64PmrlFw2w") public FunctionStateResponse functionSTATUS__Установить_статус__Замечание_зарегистрировано( FunctionStateRequest functionStateRequest) { de.metasonic.reftmpl.fieldvaluesetter.runtime.RefinementTemplateRuntime refinementRuntime = new de.metasonic.reftmpl.fieldvaluesetter.runtime.RefinementTemplateRuntime(); de.metasonic.support.context.ApplicationContextProvider.getInstance() .getApplicationContext().getAutowireCapableBeanFactory() .autowireBean(refinementRuntime); refinementRuntime .setStateConfig(DATA_FunctionStateDescription___fMQV7_EeaP64PmrlFw2w); try { return (FunctionStateResponse) refinementRuntime.execute( getSubjectInstance(), getSubjectDescription(), getClass() .getClassLoader()); } catch (Exception ex) { throw new RuntimeException(ex); } } /** * This method is called when the named function state is reached State: * Автоназначение ответственного StateType: FUNCTION * * Return values "FunctionTransitionDescription_V7Qmg26XEeaCBYqxdMxsCg" when * result is "" to go to state STATUS: Установить статус: Инцидент * зарегистрирован * * @return return the id of the transition to follow e.g. // return new * FunctionStateResponse("transitionXXXXXXXX"); */ @RefinementGenerator(id = "FunctionStateDescription_QitNcW6XEeaCBYqxdMxsCg") public FunctionStateResponse functionАвтоназначение_ответственного( FunctionStateRequest functionStateRequest) { log.error("autoassign start"); String operatorIpIdQuery = String.format( "SELECT ID AS %s FROM UM_GROUP " + "WHERE NAME = '%s'", ID_AS_IP_ID, OPERATOR_IP); String availableOperatorsQueryTemplate = String.format( "SELECT A.UM_GROUP AS %s, A.%s, B.UM_GROUP AS %s " + "FROM UM_GROUP_UM_USER AS A " + "LEFT JOIN UM_GROUP_UM_USER AS B " + "ON A.%s = B.%s " + " WHERE A.UM_GROUP = %s " + " AND B.UM_GROUP = %s", UM_GROUP_AS_INDEX, UM_USER, UM_GROUP_AS_ROLE, UM_USER, UM_USER, "%s", "%s"); String activeTasksQueryTemplate = String .format("SELECT count(*) AS %s " + " FROM ((SELECT DROPPED, AVAILABLETRANSITIONS, RT_PROCDESC, RT_SUBDESC, UM_USER_EDITOR " + " FROM RT_SUBINST " + " WHERE DROPPED = false AND " + " AVAILABLETRANSITIONS = true " + " AND UM_USER_EDITOR = %s) AS A " + " JOIN (SELECT ID, JPASS_ID, NAME " + " FROM RT_SUBDESC " + " WHERE JPASS_ID = '%s') AS B " + " ON A.RT_SUBDESC = B.ID)", ACTIVE_TASK_NUMBER, "%s", "%s"); try (final Connection connection = DbHelper.getConnection(DbHelper.PROP_DB_INT);) { log.error("connection has been set"); // find ID for OPERATOR-IP // form query as SELECT TOP 1 ID AS ... operatorIpId = getOperatorIpId(connection, operatorIpIdQuery); log.error(OPERATOR_IP + "'s ID: " + operatorIpId); // retrieve current card's postamt info IView primeBOEventCard = (IView) getPrimeBO(this.getSubjectInstance()); if (null != primeBOEventCard) { log.error("retrieving postamt data for current EventCard"); String postamtIndex = (String) BOHelper.getAttribute(primeBOEventCard, "postamtIndex"); String postamtName = (String) BOHelper.getAttribute(primeBOEventCard, "postamtName"); log.error(" postamt: " + postamtIndex + "/" + postamtName); // get operators from postamts that belong to concrete ufps // form query as ... WHERE UM_GROUP = 123456 AND UM_GROUP = 10 String availableOperatorsQuery = String.format(availableOperatorsQueryTemplate, postamtIndex,operatorIpId); Pair[] operatorUserRolePairs = getAvailableOperators(connection, availableOperatorsQuery); // now as we got available operators, lets count number of their tasks if (0 != operatorUserRolePairs.length) { log.error("iterating over [" + operatorUserRolePairs.length + "] available operators"); log.error("executing: " + String.format(activeTasksQueryTemplate, "", "")); // iterate over operators and count number of their active tasks String lazybonesId = null; int minTaskNum = Integer.MAX_VALUE; for (Pair p : operatorUserRolePairs) { String currUserId = p.getFirstElement(); // count number of active tasks for user // form query as ... WHERE A.UM_USER_EDITOR = 1337 ... WHERE B.JPASS_ID = 'InternalSubjDesc_322' String activeTasksQuery = String.format( activeTasksQueryTemplate, currUserId, responsibleSubjectDescId); int taskNum = countActiveTasks(connection, activeTasksQuery); log.error("id:taskNum (" + currUserId + ":" + taskNum + ")"); if (taskNum < minTaskNum) { minTaskNum = taskNum; lazybonesId = currUserId; } } log.error("operator to be assigned found: " + lazybonesId); BOHelper.setAttribute(primeBOEventCard, "assignedOperator", lazybonesId); log.error("saving changes"); //String field "assignedOperator" in EventCardBO should be created //============================================================================================== //-----------------------------some troubles with saving here----------------------------------- //============================================================================================== saveNewPrimeBO(this.getSubjectInstance(), primeBOEventCard); String op = (String)BOHelper.getAttribute(primeBOEventCard, "assignedOperator"); log.error("op: " + op); } else { log.error("no availble " + OPERATOR_IP + "s were found by current postamt"); } } else { log.error("error retrieving primeBO"); } log.error("all done"); log.error("\n"); } catch (Exception e) { e.printStackTrace(); } return null; } private int getOperatorIpId(Connection connection, String query) { int id = -1; try { log.error("executing: " + query); Statement stmt = connection.createStatement(); stmt.setMaxRows(1); ResultSet cgiSet = stmt.executeQuery(query); if (cgiSet.next()) id = cgiSet.getInt(ID_AS_IP_ID); cgiSet.close(); } catch (SQLException e) { log.error("error fetching " + OPERATOR_IP + "'s ID"); } return id; } private Pair[] getAvailableOperators(Connection connection, String query) { List userRolePairs = new ArrayList(); try { ResultSet result = connection.createStatement().executeQuery(query); log.error("executing: " + query); while (result.next()) { int umGroupAsIndex = result.getInt(UM_GROUP_AS_INDEX); int umUserAsId = result.getInt(UM_USER); int umGroupAsRole = result.getInt(UM_GROUP_AS_ROLE); log.error(" indx/id/role: " + umGroupAsIndex + " / " + umUserAsId + " / " + umGroupAsRole); userRolePairs.add(new Pair(String.valueOf(umUserAsId), String.valueOf(umGroupAsRole))); } result.close(); } catch (SQLException e) { e.printStackTrace(); } return userRolePairs.toArray(new Pair[0]); } private int countActiveTasks(Connection connection, String query) { int id = -1; try { // log.error("executing: " + query); Statement stmt = connection.createStatement(); stmt.setMaxRows(1); ResultSet cgiSet = stmt.executeQuery(query); if (cgiSet.next()) id = cgiSet.getInt(ACTIVE_TASK_NUMBER); cgiSet.close(); } catch (SQLException e) { log.error("error fetching task number"); } return id; } private IView getPrimeBO(ISubjectInstanceBean subjectInstanceBean) throws Exception { IBo20AccessApi bo20AccessApi = ApiUtils.lookupBo20AccessApi(); Set storages = bo20AccessApi.getStorages(subjectInstanceBean, null); IStorageInstanceBean storage = storages.iterator().next(); Set storageItems = bo20AccessApi.getItems(subjectInstanceBean, storage); IStorageInstanceItemBeanReducedToId storageItem = storageItems.iterator().next(); String actionType = BusinessObject20.Action.READ; IViewStorageInstanceItemPair storageInstanceItem = bo20AccessApi.getIViewAndItem(subjectInstanceBean, storageItem, actionType); IView iView = storageInstanceItem.getiView(); return iView; } private void saveNewPrimeBO(ISubjectInstanceBean subjectInstanceBean, IView iView) throws Exception { log.error("looking for api"); IBo20AccessApi bo20AccessApi = ApiUtils.lookupBo20AccessApi(); log.error("retrieving storages"); Set storages = bo20AccessApi.getStorages(subjectInstanceBean, null); log.error("retrieving single storage"); IStorageInstanceBean storage = storages.iterator().next(); log.error("saving"); bo20AccessApi.saveNewIViewInStorage(subjectInstanceBean, iView, storage); log.error("done"); } /** * @generated */ private static final String DATA_FunctionStateDescription_UebAgV7xEeaP64PmrlFw2w = "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48Y29uZmlndXJhdGlvbj48U1RBVEVfSUQgdmFsdWU9IkZ1bmN0aW9uU3RhdGVEZXNjcmlwdGlvbl9VZWJBZ1Y3eEVlYVA2NFBtcmxGdzJ3Ii8+PGJvMjBfZmllbGQuYm8gdmFsdWU9InJ1Lml0Lm1ldGFzb25pYy5ydXNwb3N0LmluZm9wb2ludC5kYXRhLmV2ZW50Y2FyZC5FdmVudENhcmRJbml0VmlldyIvPjxzdG9yYWdlLnZhbHVlIHZhbHVlPSJCT1N0b3JhZ2VEZXNjcmlwdGlvbl8xSHBnMERlX0VlYVFzcEtDTlFPU25BIi8+PGJvMjBfZmllbGQudHlwZS4xIHZhbHVlPSJFTlVNIi8+PGJvMjBfZmllbGQudmFsdWUuMSB2YWx1ZT0iaW5jaWRlbnRJc1JlZ2lzdGVyZWQiLz48Ym8yMF9maWVsZC5tb2RlIHZhbHVlPSJjaGVjayIvPjxibzIwX2ZpZWxkLmZpZWxkLjEgdmFsdWU9InN0YXR1cyIvPjxibzIwX2ZpZWxkLnN0b3JhZ2UgdmFsdWU9IkJPU3RvcmFnZURlc2NyaXB0aW9uXzFIcGcwRGVfRWVhUXNwS0NOUU9TbkEiLz48L2NvbmZpZ3VyYXRpb24+"; }