Example usage for java.util Collections shuffle

List of usage examples for java.util Collections shuffle

Introduction

In this page you can find the example usage for java.util Collections shuffle.

Prototype

@SuppressWarnings({ "rawtypes", "unchecked" })
public static void shuffle(List<?> list, Random rnd) 

Source Link

Document

Randomly permute the specified list using the specified source of randomness.

Usage

From source file:com.github.cc007.sciencespinoffsquiz.web.controllers.RequestController.java

@RequestMapping(value = "/quiz", method = RequestMethod.GET)
public String quiz(@ModelAttribute("userid") String userId, @ModelAttribute("answer") String answer,
        @ModelAttribute("random") String random, @ModelAttribute("questionNr") String questionNr,
        @ModelAttribute("language") String language, @ModelAttribute("gender") String gender,
        @ModelAttribute("ageGroup") String ageGroup, @ModelAttribute("restart") String restart, ModelMap map) {
    long newRandom;
    GameStatisticsStorage gss;/*from w  w  w. j  a va2 s.c om*/
    LanguagesController lc;
    System.out.println("Incoming request:");
    if ("restart".equals(restart)) {
        System.out.println(" Restart quiz");
        map.put("quizredirect", "<meta http-equiv=\"refresh\" content=\"0;url=/ScienceSpinoffsQuiz/quiz\" />");
        return "index";
    }
    if (!"".equals(userId) && IntegerChecker.isInteger(userId)) {
        gss = new DatabaseStorage(Integer.parseInt(userId));
        System.out.println(" UserId is set.");
    } else {
        System.out.println(" UserId is not set yet.\n");
        if ("".equals(language)) {
            return "index";
        }
        lc = new LanguagesController(language);
        if ("".equals(gender)) {
            map.put("language", language);
            map.put("genderQuestion", lc.getText("GenderQuestion"));
            map.put("male", lc.getText("Male"));
            map.put("female", lc.getText("Female"));
            return "gender";
        }

        if ("".equals(ageGroup)) {
            map.put("language", language);
            map.put("gender", gender);
            map.put("ageGroupQuestion", lc.getText("AgeGroupQuestion"));
            map.put("younger", lc.getText("Younger"));
            map.put("older", lc.getText("Older"));
            return "agegroup";
        }

        //TODO create id
        gss = new DatabaseStorage();
        gss.setGender(gender);
        gss.setAgeGroup(ageGroup);
        userId = gss.getUserId() + "";

        gss.saveStatistics();

    }
    if (!"".equals(random) && IntegerChecker.isInteger(random)) {
        System.out.println(" Random is set.");
        newRandom = Long.parseLong(random);
    } else {
        System.out.println(" Random was not set");
        newRandom = System.currentTimeMillis();
    }

    System.out.println(" Retrieving question...");
    String xmlFileName = "questions_en.xml";
    if (!"".equals(language)) {
        lc = new LanguagesController(language);
        switch (language.toLowerCase()) {
        case "nederlands":
            xmlFileName = "questions_nl.xml";
            break;
        case "english":
            xmlFileName = "questions_en.xml";
            break;
        }
    } else {
        lc = new LanguagesController("English");
    }
    QuestionPool qp = new QuestionPool(xmlFileName);
    int newQuestionNr = 0;
    if (!"".equals(questionNr) && IntegerChecker.isInteger(questionNr)) {
        newQuestionNr = Integer.parseInt(questionNr);
        System.out.println("  Question is set.");
    } else {
        System.out.println("  No question set: assuming first question.");
    }
    List<Question> questions = qp.getQuestions();
    Collections.shuffle(questions, new Random(newRandom));
    if (newQuestionNr >= questions.size()) {
        map.put("endQuiz", lc.getText("EndQuiz"));
        map.put("restartQuiz", lc.getText("RestartQuiz"));
        return "endquiz";
    }
    Question q = questions.get(newQuestionNr);

    if (!"".equals(answer)) {
        Answer givenAnswer = Answer.fromString(answer);
        boolean right = givenAnswer != null && q.getRightAnswer().equalsAnswer(givenAnswer);
        System.out.println("Store result in database");
        gss.setScore(q.getId(), right);
        gss.saveStatistics();

        System.out.println(" Prepare explanation webview");
        map.put("explanation", q.getExplanation());
        if (right) {
            map.put("questionText", lc.getText("RightAnswer") + q.getRightAnswer().toString());
        } else {
            map.put("questionText", lc.getText("WrongAnswer") + q.getRightAnswer().toString());
        }
        map.put("userid", userId);
        map.put("random", newRandom + "");
        map.put("questionNr", newQuestionNr + 1 + "");
        map.put("language", language);
        map.put("imgName", q.getExplanationImage());
        map.put("nextQuestion", lc.getText("NextQuestion"));
        map.put("restartQuiz", lc.getText("RestartQuiz"));
        return "explanation";
    }

    System.out.println(" Prepare question in webview");
    map.put("question", q.getQuestion());
    map.put("answerA", q.getAnswerA());
    map.put("answerB", q.getAnswerB());
    map.put("answerC", q.getAnswerC());
    map.put("userid", userId);
    map.put("random", newRandom + "");
    map.put("questionNr", newQuestionNr + "");
    map.put("language", language);

    System.out.println("Request handled.\n");

    return "question";
}

From source file:cerrla.modular.ModularPolicy.java

/**
 * Evaluates the rules of this policy (with recursion).
 * // w  w w  . jav  a2  s  . c  o m
 * @param observations
 *            The relational observations for the state.
 * @param policyActions
 *            The collection to add the actions to.
 * @param activatedActions
 *            The actions the RLGG rules return.
 * @param actionsFound
 *            The number of actions found so far.
 * @param actionsRequired
 *            The number of actions required to return.
 * @return The resultant actions.
 * @throws Exception
 *             Should something go awry...
 */
private void evaluateInternalPolicy(RRLObservations observations, PolicyActions policyActions,
        MultiMap<String, String[]> activatedActions, int actionsFound, int actionsRequired) throws Exception {
    firedLastStep_.clear();

    // Run the cover state method to possibly scan this state (depending on
    // current RLGG rules and scan intervals).
    List<RelationalRule> coveredRules = ceDistribution_.coverState(this, observations, activatedActions,
            episodeGoalReplacements_);
    // If the policy is empty, store the rules in it.
    if (coveredRules != null && !coveredRules.isEmpty()) {
        Collections.shuffle(coveredRules, RRLExperiment.random_);
        // Add any new rules to the policy
        for (RelationalRule gr : coveredRules) {
            policyRules_.add(gr);
            policySize_++;
        }
        // Add parameters to the rule.
        parameterArgs(transformGoalReplacements(observations.getGoalReplacements()));
    }

    // If the goal has been achieved, don't evaluate this policy
    if (goalAchievedCurrently_)
        return;

    // Evaluate the rules/policies recursively.
    Rete state = observations.getState();

    Iterator<PolicyItem> iter = policyRules_.iterator();
    while (iter.hasNext() && actionsFound < actionsRequired) {
        Object polObject = iter.next();
        if (polObject instanceof RelationalRule) {
            // Evaluate the rule
            RelationalRule polRule = (RelationalRule) polObject;
            Collection<FiredAction> firedActions = evaluateRule(polRule, state,
                    observations.getValidActions(polRule.getActionPredicate()), null, true);
            policyActions.addFiredRule(firedActions, this);
            actionsFound += firedActions.size();

            // If this rule created a sub-goal, mark the goal achieved.
            if (childrenPolicies_.containsKey(polRule)) {
                for (ModularSubGoal modSubGoal : childrenPolicies_.get(polRule)) {
                    if (!firedActions.isEmpty())
                        modSubGoal.setGoalAchieved(true);
                    else
                        modSubGoal.setGoalAchieved(false);
                }
            }
        } else if (polObject instanceof ModularSubGoal) {
            // Evaluate the internal policy.
            ModularPolicy internalPolicy = ((ModularSubGoal) polObject).getModularPolicy();
            if (internalPolicy != null)
                internalPolicy.evaluateInternalPolicy(observations, policyActions, activatedActions,
                        actionsFound, actionsRequired);
        }
    }
}

From source file:ch.blinkenlights.android.vanilla.MediaUtils.java

/**
 * Shuffle a Song list using Collections.shuffle().
 *
 * @param albumShuffle If true, preserve the order of songs inside albums.
 *//*from  w  w  w.  j av  a 2s. c  o m*/
public static void shuffle(List<Song> list, boolean albumShuffle) {
    int size = list.size();
    if (size < 2)
        return;

    Random random = getRandom();
    if (albumShuffle) {
        List<Song> tempList = new ArrayList<Song>(list);
        Collections.sort(tempList);

        // Build map of albumId to start index in sorted list
        Map<Long, Integer> albumStartIndices = new HashMap<Long, Integer>();
        int index = 0;
        for (Song song : tempList) {
            if (!albumStartIndices.containsKey(song.albumId)) {
                albumStartIndices.put(song.albumId, index);
            }
            index++;
        }

        //Extract album list and shuffle
        List<Long> shuffledAlbums = new ArrayList<Long>(albumStartIndices.keySet());
        Collections.shuffle(shuffledAlbums, random);

        //Build Song list from album list
        list.clear();
        for (Long albumId : shuffledAlbums) {
            int songIndex = albumStartIndices.get(albumId);
            Song song = tempList.get(songIndex);
            do {
                list.add(song);
                songIndex++;
                if (songIndex < size) {
                    song = tempList.get(songIndex);
                } else {
                    break;
                }
            } while (albumId == song.albumId);
        }
    } else {
        Collections.shuffle(list, random);
    }
}

From source file:edu.byu.nlp.crowdsourcing.ModelInitializationTest.java

public static String jsonInstances(long seed) {
    List<String> jsonInstances = Lists.newArrayList(
            "{\"batch\": 0, \"data\":\"ABCD\", \"endTime\":5, \"label\":\"0\",                           \"source\":1,     \"startTime\":0 }", // label
            "{\"batch\": 1, \"data\":\"ABCD\", \"endTime\":6, \"annotation\":\"0\", \"annotator\":\"A\", \"source\":1,     \"startTime\":0 }", // annotation to the same doc
            "{\"batch\": 2, \"data\":\"ABCD\", \"endTime\":7, \"annotation\":\"1\", \"annotator\":\"B\", \"source\":1,     \"startTime\":0 }", // annotation to the same doc
            "{\"batch\": 2, \"data\":\"ABCD\", \"endTime\":8, \"annotation\":\"0\", \"annotator\":\"B\", \"source\":1,     \"startTime\":0 }", // annotation to the same doc
            "{\"batch\": 0, \"data\":\"ABCD\", \"endTime\":1, \"label\":\"1\",                           \"source\":2,     \"startTime\":0 }", // label 
            "{\"batch\": 1, \"data\":\"ABCD\", \"endTime\":2, \"annotation\":\"0\", \"annotator\":\"A\", \"source\":2,     \"startTime\":0 }", // annotation to the same doc
            "{\"batch\": 2, \"data\":\"ABCD\", \"endTime\":3, \"annotation\":\"1\", \"annotator\":\"B\", \"source\":2,     \"startTime\":0 }", // annotation to the same doc
            "{\"batch\": 2, \"data\":\"ABCD\", \"endTime\":4, \"annotation\":\"1\", \"annotator\":\"B\", \"source\":2,     \"startTime\":0 }", // annotation to the same doc
            "{\"batch\": 0, \"data\":\"ABCD\", \"endTime\":9, \"label\":\"0\",                           \"source\":3,     \"startTime\":0 }", // label
            "{\"batch\": 1, \"data\":\"ABCD\", \"endTime\":10, \"annotation\":\"1\", \"annotator\":\"A\", \"source\":3,     \"startTime\":0 }", // annotation to the same doc
            "{\"batch\": 2, \"data\":\"ABCD\", \"endTime\":11, \"annotation\":\"0\", \"annotator\":\"B\", \"source\":3,     \"startTime\":0 }", // annotation to the same doc
            "{\"batch\": 2, \"data\":\"ABCD\", \"endTime\":12, \"annotation\":\"0\", \"annotator\":\"B\", \"source\":3,     \"startTime\":0 }", // annotation to the same doc
            "{\"batch\": 0, \"data\":\"ABCD\", \"endTime\":13, \"label\":\"0\",                           \"source\":4,     \"startTime\":0 }" // label
    );/*from  w w  w .  ja  v  a 2  s  . c  o  m*/
    Random rand = new Random(seed);
    Collections.shuffle(jsonInstances, rand); // try different orderings
    return "[ \n" + Joiner.on(", \n").join(jsonInstances) + "]";

}

From source file:org.apache.solr.handler.component.AlfrescoHttpShardHandlerFactory.java

/**
 * Creates a randomized list of urls for the given shard.
 *
 * @param shard the urls for the shard, separated by '|'
 * @return A list of valid urls (including protocol) that are replicas for the shard
 *///from www.  j  a  v a 2s .  com
public List<String> makeURLList(String shard) {
    List<String> urls = StrUtils.splitSmart(shard, "|", true);

    // convert shard to URL
    for (int i = 0; i < urls.size(); i++) {
        urls.set(i, buildUrl(urls.get(i)));
    }

    //
    // Shuffle the list instead of use round-robin by default.
    // This prevents accidental synchronization where multiple shards could get in sync
    // and query the same replica at the same time.
    //
    if (urls.size() > 1)
        Collections.shuffle(urls, r);

    return urls;
}

From source file:iDynoOptimizer.MOEAFramework26.src.org.moeaframework.core.PRNG.java

/**
 * Shuffles the elements of the specified list by invoking the
 * {@link Collections#shuffle} method with the internal {@link Random} in
 * this PRNG./*from   w  w  w.  j a va  2 s  . c  om*/
 * 
 * @param <T> the type of elements stored in the list
 * @param list the list to be shuffled
 */
public static <T> void shuffle(List<T> list) {
    Collections.shuffle(list, random);
}

From source file:edu.mssm.crover.tables.writers.LibSVMWriter.java

/**
 * Run cross-validation with k folds./*  w  ww . ja  v a 2 s  .c  o m*/
 *
 * @param k Number of folds for cross validation. Typical values are 5 or 10.
 * @return Evaluation measures.
 */
public EvaluationMeasure crossValidation(final int k) {
    assert tableScanned : " Must process rows of input table first.";
    assert k <= numberOfTrainingExamples : "Number of folds must be less or equal to number of training examples.";
    final IntList indices = new IntArrayList();
    for (int f = 0; f < k; ++f) {
        for (int i = 0; i < numberOfTrainingExamples / k; ++i) {
            indices.add(f);
        }
    }
    Collections.shuffle(indices, randomAdapter);

    final int[] splitIndex = new int[numberOfTrainingExamples];
    indices.toArray(splitIndex);

    final ContingencyTable ctable = new ContingencyTable();
    for (int f = 0; f < k; ++f) { // use each fold as test set while the others are the training set:
        final IntSet trainingSet = new IntArraySet();
        final IntSet testSet = new IntArraySet();
        for (int i = 0; i < numberOfTrainingExamples; i++) { // assign each training example to a fold:
            if (f == splitIndex[i]) {
                testSet.add(i);
            } else {
                trainingSet.add(i);
            }
        }
        //   System.out.println("trainingSet: " + trainingSet.toString());
        //  System.out.println("splitSpecificTestSet: " + splitSpecificTestSet.toString());
        final svm_problem currentTrainingSet = splitProblem(problem, trainingSet);
        final svm_model looModel = svm.svm_train(currentTrainingSet, parameters);
        final ContingencyTable ctableMicro = new ContingencyTable();

        for (final int testInstanceIndex : testSet) { // for each test example:
            final double decision = svm.svm_predict(looModel, problem.x[testInstanceIndex]);
            final double trueLabel = problem.y[testInstanceIndex];
            ctable.observeDecision(trueLabel, decision);
            ctableMicro.observeDecision(trueLabel, decision);
        }
        ctableMicro.average();
        // System.out.println("microaverage: " + convertToEvalMeasure(ctableMicro));
    }
    ctable.average();
    //      System.out.println("macroaverage: "+convertToEvalMeasure(ctable));
    return convertToEvalMeasure(ctable);
}

From source file:org.elasticsearch.client.sniff.ElasticsearchNodesSnifferTests.java

private static SniffResponse buildSniffResponse(ElasticsearchNodesSniffer.Scheme scheme) throws IOException {
    int numNodes = RandomNumbers.randomIntBetween(getRandom(), 1, 5);
    List<Node> nodes = new ArrayList<>(numNodes);
    JsonFactory jsonFactory = new JsonFactory();
    StringWriter writer = new StringWriter();
    JsonGenerator generator = jsonFactory.createGenerator(writer);
    generator.writeStartObject();//from  w  w  w  .  j a va 2s  . c om
    if (getRandom().nextBoolean()) {
        generator.writeStringField("cluster_name", "elasticsearch");
    }
    if (getRandom().nextBoolean()) {
        generator.writeObjectFieldStart("bogus_object");
        generator.writeEndObject();
    }
    generator.writeObjectFieldStart("nodes");
    for (int i = 0; i < numNodes; i++) {
        String nodeId = RandomStrings.randomAsciiOfLengthBetween(getRandom(), 5, 10);
        String host = "host" + i;
        int port = RandomNumbers.randomIntBetween(getRandom(), 9200, 9299);
        HttpHost publishHost = new HttpHost(host, port, scheme.toString());
        Set<HttpHost> boundHosts = new HashSet<>();
        boundHosts.add(publishHost);

        if (randomBoolean()) {
            int bound = between(1, 5);
            for (int b = 0; b < bound; b++) {
                boundHosts.add(new HttpHost(host + b, port, scheme.toString()));
            }
        }

        int numAttributes = between(0, 5);
        Map<String, List<String>> attributes = new HashMap<>(numAttributes);
        for (int j = 0; j < numAttributes; j++) {
            int numValues = frequently() ? 1 : between(2, 5);
            List<String> values = new ArrayList<>();
            for (int v = 0; v < numValues; v++) {
                values.add(j + "value" + v);
            }
            attributes.put("attr" + j, values);
        }

        Node node = new Node(publishHost, boundHosts, randomAsciiAlphanumOfLength(5),
                randomAsciiAlphanumOfLength(5),
                new Node.Roles(randomBoolean(), randomBoolean(), randomBoolean()), attributes);

        generator.writeObjectFieldStart(nodeId);
        if (getRandom().nextBoolean()) {
            generator.writeObjectFieldStart("bogus_object");
            generator.writeEndObject();
        }
        if (getRandom().nextBoolean()) {
            generator.writeArrayFieldStart("bogus_array");
            generator.writeStartObject();
            generator.writeEndObject();
            generator.writeEndArray();
        }
        boolean isHttpEnabled = rarely() == false;
        if (isHttpEnabled) {
            nodes.add(node);
            generator.writeObjectFieldStart("http");
            generator.writeArrayFieldStart("bound_address");
            for (HttpHost bound : boundHosts) {
                generator.writeString(bound.toHostString());
            }
            generator.writeEndArray();
            if (getRandom().nextBoolean()) {
                generator.writeObjectFieldStart("bogus_object");
                generator.writeEndObject();
            }
            generator.writeStringField("publish_address", publishHost.toHostString());
            if (getRandom().nextBoolean()) {
                generator.writeNumberField("max_content_length_in_bytes", 104857600);
            }
            generator.writeEndObject();
        }

        List<String> roles = Arrays.asList(new String[] { "master", "data", "ingest" });
        Collections.shuffle(roles, getRandom());
        generator.writeArrayFieldStart("roles");
        for (String role : roles) {
            if ("master".equals(role) && node.getRoles().isMasterEligible()) {
                generator.writeString("master");
            }
            if ("data".equals(role) && node.getRoles().isData()) {
                generator.writeString("data");
            }
            if ("ingest".equals(role) && node.getRoles().isIngest()) {
                generator.writeString("ingest");
            }
        }
        generator.writeEndArray();

        generator.writeFieldName("version");
        generator.writeString(node.getVersion());
        generator.writeFieldName("name");
        generator.writeString(node.getName());

        if (numAttributes > 0) {
            generator.writeObjectFieldStart("attributes");
            for (Map.Entry<String, List<String>> entry : attributes.entrySet()) {
                if (entry.getValue().size() == 1) {
                    generator.writeStringField(entry.getKey(), entry.getValue().get(0));
                } else {
                    for (int v = 0; v < entry.getValue().size(); v++) {
                        generator.writeStringField(entry.getKey() + "." + v, entry.getValue().get(v));
                    }
                }
            }
            generator.writeEndObject();
        }
        generator.writeEndObject();
    }
    generator.writeEndObject();
    generator.writeEndObject();
    generator.close();
    return SniffResponse.buildResponse(writer.toString(), nodes);
}

From source file:jenkins.security.apitoken.ApiTokenStatsTest.java

@Test
@SuppressWarnings("unchecked")
public void testInternalComparator() throws Exception {
    List<ApiTokenStats.SingleTokenStats> tokenStatsList = Arrays.asList(
            createSingleTokenStatsByReflection("A", null, 0),
            createSingleTokenStatsByReflection("B", "2018-05-01 09:10:59.234", 2),
            createSingleTokenStatsByReflection("C", "2018-05-01 09:10:59.234", 3),
            createSingleTokenStatsByReflection("D", "2018-05-01 09:10:59.235", 1));

    Field field = ApiTokenStats.SingleTokenStats.class.getDeclaredField("COMP_BY_LAST_USE_THEN_COUNTER");
    field.setAccessible(true);/*ww  w  . j  a va 2 s .  com*/
    Comparator<ApiTokenStats.SingleTokenStats> comparator = (Comparator<ApiTokenStats.SingleTokenStats>) field
            .get(null);

    // to be not impacted by the declaration order
    Collections.shuffle(tokenStatsList, new Random(42));
    tokenStatsList.sort(comparator);

    List<String> idList = tokenStatsList.stream().map(ApiTokenStats.SingleTokenStats::getTokenUuid)
            .collect(Collectors.toList());

    assertThat(idList, contains("A", "B", "C", "D"));
}

From source file:it.uniroma2.sag.kelp.learningalgorithm.classification.dcd.DCDLearningAlgorithm.java

@Override
public void learn(Dataset dataset) {

    if (isFairness() && cp == cn) {
        float positiveExample = dataset.getNumberOfPositiveExamples(label);
        float negativeExample = dataset.getNumberOfNegativeExamples(label);

        cp = cn * negativeExample / positiveExample;
    }//from   ww  w  . ja va  2s  .co m

    List<Example> vecs = dataset.getExamples();
    float[] alpha = new float[vecs.size()];
    float[] y = new float[vecs.size()];
    float bias = 0;
    double[] Qhs = new double[vecs.size()];// Q hats

    double[] U = new double[vecs.size()];
    double[] D = new double[vecs.size()];

    for (int i = 0; i < dataset.getNumberOfExamples(); i++) {
        Example ei = dataset.getExamples().get(i);

        y[i] = getY(ei);

        U[i] = getU(ei);

        D[i] = getD(ei);

        Vector vecI = (Vector) dataset.getExamples().get(i).getRepresentation(representation);

        Qhs[i] = vecI.innerProduct(vecI) + D[i];
        if (useBias)
            Qhs[i] += 1.0;
    }

    if (this.getPredictionFunction().getModel().getHyperplane() == null) {
        this.getPredictionFunction().getModel().setHyperplane(dataset.getZeroVector(representation));
    }

    Vector w = this.getPredictionFunction().getModel().getHyperplane();

    // Vector v0 = (Vector) dataset.getExamples().get(0)
    // .getRepresentation(representation);
    // Vector w = v0.getZeroVector();

    List<Integer> A = new ArrayList<Integer>();
    for (int i = 0; i < dataset.getNumberOfExamples(); i++) {
        A.add(i);
    }

    Random rand = new Random(seed);

    for (int t = 0; t < maxIterations; t++) {

        Collections.shuffle(A, rand);

        for (int i : A) {
            // * Performs steps a, b, and c of the DCD algorithms 1 and 2
            Vector vecI = (Vector) dataset.getExamples().get(i).getRepresentation(representation);

            // a
            final double G = y[i] * (w.innerProduct(vecI) + bias) - 1 + D[i] * alpha[i];
            // b
            final double PG;
            if (alpha[i] == 0)
                PG = Math.min(G, 0);
            else if (alpha[i] == U[i])
                PG = Math.max(G, 0);
            else
                PG = G;
            // c
            if (PG != 0) {
                float alphaOld = alpha[i];
                alpha[i] = (float) Math.min(Math.max(alpha[i] - G / Qhs[i], 0), U[i]);
                float scale = (alpha[i] - alphaOld) * y[i];
                w.add(scale, vecI);
                if (useBias)
                    bias += scale;
            }
        }

    }

    this.classifier.getModel().setHyperplane(w);
    this.classifier.getModel().setRepresentation(representation);
    if (useBias)
        this.classifier.getModel().setBias(bias);
    else
        this.classifier.getModel().setBias(0);
}