class ZNNStateAnalyzer extends AbstractRainbowRunnable implements IRainbowAnalysis, IModelChangeBusSubscriberPort.IRainbowModelChangeCallback {

    @Override
    protected void runAction () {
        final ZNNModelUpdateOperatorsImpl model = m_modelCheckQ.poll ();
        if (model != null) {
            Stack<AcmeError> errors = new Stack<> ();
            IAcmeSystem system = model.getModelInstance ();

            if (m_clientsSelection != null && m_maliciousSelection != null) {
                NodeScopeLookup lookup = new NodeScopeLookup ();
                try {
                    AcmeSet clients = RuleTypeChecker.evaluateAsSet (system, null, m_clientsSelection, errors, lookup);

//                    AcmeSet maliciousClients = RuleTypeChecker.evaluateAsSet (system, null, m_maliciousSelection, errors, lookup);
                    boolean aboveMal = RuleTypeChecker.evaluateAsBoolean (system, null, m_aboveMal, errors, lookup);
                    boolean aboveRT = RuleTypeChecker.evaluateAsBoolean (system, null, m_aboveRT, errors, lookup);
                    float avgRT = 0.0f;
                    float perMal = 0.0f;
                    if (clients != null) {
                        float cum = 0.0f;
                        int numMal = 0;
                        for (Object o : clients.getValues ()) {
                            IAcmeProperty prop;
                            float mal = 0;
                            if (o instanceof IAcmeElementInstance) {
                                IAcmeElementInstance client = (IAcmeElementInstance) o;
                                if ((prop = client.getProperty ("experRespTime")) != null) {
                                    cum += ((IAcmeFloatingPointValue) prop.getValue ()).getFloatValue ();
                                }
                                if ((prop = client.getProperty ("maliciousness")) != null) {
                                    mal = ((IAcmeFloatingPointValue) prop.getValue ()).getFloatValue ();
                                    log (MessageFormat.format ("{0}.maliciousness={1}", client, mal));
                                    if (mal > 0.5) {
                                        numMal++;
                                    }
                                }
                            }
                        }
                        avgRT = cum / clients.getValues ().size ();
                        perMal = ((float) numMal) / clients.getValues ().size () * 100f;
                        SetSystemPropertiesCmd cmd = model.getCommandFactory ().setSystemProperties (system, avgRT, perMal, aboveRT, aboveMal);
                        m_modelUSPort.updateModel (cmd);

                    }


                } catch (AcmeException e) {
                    m_reportingPort.error (RainbowComponentT.ANALYSIS, "Failed to evaluate an expression", e);
                }

            }


        }

    }

    public  ZNNStateAnalyzer();

}