text:
package ch.fhnw.jobannotations.extractors.skills;

import ch.fhnw.jobannotations.domain.JobOffer;
import ch.fhnw.jobannotations.extractors.IExtractor;
import ch.fhnw.jobannotations.utils.*;
import com.aliasi.dict.TrieDictionary;
import edu.stanford.nlp.ling.IndexedWord;
import edu.stanford.nlp.semgraph.SemanticGraph;
import edu.stanford.nlp.semgraph.SemanticGraphCoreAnnotations;
import edu.stanford.nlp.trees.EnglishGrammaticalRelations;
import edu.stanford.nlp.trees.TypedDependency;
import edu.stanford.nlp.util.CoreMap;
import org.apache.log4j.Logger;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * This class is responsible to identify potential skills in a job offer document. To prevent false results and to
 * improve performance, various techniques are used.
 *
 * @author Hoang Tran <hoang.tran@students.fhnw.ch>
 */
public class SkillExtractor implements IExtractor {

    private final static Logger LOG = Logger.getLogger(SkillExtractor.class);

    @Override
    public String parse(JobOffer jobOffer) {

        LOG.debug("Started to parse skills from offer by checking lists");

        Map<IntStringPair, List<String>> ratedSkillLists = extractSkillListsByListParsing(jobOffer);

        if (ratedSkillLists.isEmpty()) {
            // no skills found
            LOG.debug("No skills found with list parsing. Started to parse skills from offer by analysing sentences with NLP");

            ratedSkillLists = extractSkillListsBySentenceAnalyzing(jobOffer);
            if (ratedSkillLists.isEmpty()) {
                return null;
            }
        }

        LOG.debug("No skills found.");
        LOG.debug("Extract nouns from skill lists");

        formatSkills(ratedSkillLists);

        // create single skill list
        HashSet<String> mergedSkillList = new HashSet<>();
        for (IntStringPair ratedListTitle : ratedSkillLists.keySet()) {
            List<String> skills = ratedSkillLists.get(ratedListTitle);
            mergedSkillList.addAll(skills);
        }

        return generateSkillListPrintout(mergedSkillList);
    }

    @Override
    public void learn(String data) {
        if (!StringUtils.isEmpty(data)) {
            data = data.replaceAll(SkillExtractorConstants.SEPARATOR, "\n");
            FileUtils.addDataToTrainFile(ConfigurationUtil.get("extraction.skills.train.positive"), data);
        }
    }

    /**
     * Formats skills of given skill List Map by extracting nouns from the sentences.
     * @param ratedSkillLists Formatted skill List Map
     */
    private void formatSkills(Map<IntStringPair, List<String>> ratedSkillLists) {
        for (IntStringPair listTitle : ratedSkillLists.keySet()) {
            List<String> skillSentences = ratedSkillLists.get(listTitle);

            List<String> formattedSkills = extractSkills(skillSentences);

            // replace old list
            ratedSkillLists.put(listTitle, formattedSkills);
        }
    }

    /**
     * Extracts nouns of given List of skill sentences
     *
     * @param skillSentences List of skill sentences
     * @return List of skill nouns
     */
    private List<String> extractSkills(List<String> skillSentences) {
        List<String> extractedNouns = NlpHelper.getInstance().extractNouns(skillSentences);
        return filterSkillNouns(extractedNouns);
    }

    /**
     * Filters given List of potential skill nouns by rating the probability of being a skill noun and removing those
     * with bad rating.
     *
     * @param nouns List of potential skill nouns
     * @return Filtered List
     */
    private List<String> filterSkillNouns(List<String> nouns) {
        List<IntStringPair> ratedSkillNouns = new ArrayList<>();
        for (String noun : nouns) {
            int rating = calcSkillNounRating(noun);
            IntStringPair ratedSkillNoun = new IntStringPair(rating, noun);
            if (ratedSkillNoun.getInt() >= 0) {
                ratedSkillNouns.add(ratedSkillNoun);
            }

        }

        ratedSkillNouns.sort((o1, o2) -> o2.getInt() - o1.getInt());

        LOG.debug("Rate skill nouns with dictionaries");
        List<String> skills = new ArrayList<>();
        for (IntStringPair ratedSkillNoun : ratedSkillNouns) {
            LOG.debug(ratedSkillNoun.getString() + " => " + ratedSkillNoun.getInt());
            skills.add(ratedSkillNoun.getString());
        }

        return skills;
    }

    /**
     * Calculates rating of given potential skill noun by comparing it with dictionaries of known skills and known anti
     * skill.
     *
     * @param noun Potential skill noun
     * @return Calculated rating
     */
    private int calcSkillNounRating(String noun) {
        String simplifiedNoun = StringUtils.simplify(noun);

        // dictionaries
        TrieDictionary<String> skillsDictionary = NlpHelper.getInstance().getSkillsDictionary();
        TrieDictionary<String> antiSkillsDictionary = NlpHelper.getInstance().getAntiSkillsDictionary();

        // get distances
        IntStringPair skillWordDistance = getDictionaryNounDistance(skillsDictionary, noun);
        IntStringPair antiSkillWordDistance = getDictionaryNounDistance(antiSkillsDictionary, noun);
        IntStringPair simplifiedSkillWordDistance = getDictionaryNounDistance(skillsDictionary, simplifiedNoun);
        IntStringPair simplifiedAntiSkillWordDistance = getDictionaryNounDistance(antiSkillsDictionary, simplifiedNoun);

        // combine distances
        int skillDistance = 0;
        if (skillWordDistance != null) {
            skillDistance += skillWordDistance.getInt();
        } else {
            skillDistance += SkillExtractorConstants.SKILL_NOUN_DEFAULT_DISTANCE_ADJUST_VALUE;
        }
        if (simplifiedSkillWordDistance != null) {
            skillDistance += simplifiedSkillWordDistance.getInt();
        } else {
            skillDistance += SkillExtractorConstants.SKILL_NOUN_DEFAULT_DISTANCE_ADJUST_VALUE;
        }

        int antiSkillDistance = 0;
        if (antiSkillWordDistance != null) {
            antiSkillDistance += antiSkillWordDistance.getInt();
        } else {
            antiSkillDistance += SkillExtractorConstants.SKILL_NOUN_DEFAULT_DISTANCE_ADJUST_VALUE;
        }
        if (simplifiedAntiSkillWordDistance != null) {
            antiSkillDistance += simplifiedAntiSkillWordDistance.getInt();
        } else {
            antiSkillDistance += SkillExtractorConstants.SKILL_NOUN_DEFAULT_DISTANCE_ADJUST_VALUE;
        }

        if (antiSkillDistance > (SkillExtractorConstants.SKILL_NOUN_DEFAULT_DISTANCE_ADJUST_VALUE / 3 * 2)) {
            // special case for acronyms
            if (noun.contains("-")) {
                for (String part : noun.split("-")) {
                    if (StringUtils.isAllUpperCase(part.trim())) {
                        skillDistance -= (SkillExtractorConstants.SKILL_NOUN_DEFAULT_DISTANCE_ADJUST_VALUE / 3);
                    }
                }
            } else if (StringUtils.isAllUpperCase(noun)) {
                skillDistance -= SkillExtractorConstants.SKILL_NOUN_DEFAULT_DISTANCE_ADJUST_VALUE / 2;
            }
        }

        // check diff
        return antiSkillDistance - skillDistance;
    }

    /**
     * Calculates distance of given noun to entries of given dictionary.
     *
     * @param dictionary Dictionary to be used for comparison
     * @param noun       Noun to be used for comparison
     * @return IntStringPair of calculated distance and the word that has been analysed
     */
    private IntStringPair getDictionaryNounDistance(TrieDictionary<String> dictionary, String noun) {
        // calculate max distance
        int nounLength = noun.length();
        int maxDistance = 0;
        if (nounLength > 4) {
            maxDistance = 1 + nounLength / 10;
        }
        return NlpHelper.getInstance().calcDistanceWithDictionary(dictionary, noun, maxDistance);
    }

    /**
     * Extracts Lists of skills from given job offer and creates a Map with the title of the skill list as the key and
     * the List of skills as the value.
     *
     * @param jobOffer Job offer to be parsed
     * @return Map of skill Lists and their titles
     */
    private Map<IntStringPair, List<String>> extractSkillListsByListParsing(JobOffer jobOffer) {
        Map<IntStringPair, List<String>> ratedSkillLists = new HashMap<>();

        // add skill lists by getting html list elements
        Map<IntStringPair, List<String>> skillListsByHtmlTags = extractSkillListsByHtmlTags(jobOffer);
        ratedSkillLists.putAll(skillListsByHtmlTags);

        // add skill lists by using list pattern
        Map<IntStringPair, List<String>> skillListsByPattern = extractSkillListsByPattern(jobOffer);
        ratedSkillLists.putAll(skillListsByPattern);

        // calculate rating for skill lists
        LOG.debug("Rate skill list titles.");
        List<IntStringPair> ratedSkillListTitles = new ArrayList<>();
        for (IntStringPair ratedListTitle : ratedSkillLists.keySet()) {
            List<String> listItems = ratedSkillLists.get(ratedListTitle);
            String listTitle = ratedListTitle.getString();
            int rating = calcSkillListRating(jobOffer, listTitle, listItems);
            ratedListTitle.addInt(rating);
            ratedSkillListTitles.add(ratedListTitle);
            LOG.debug(listTitle + " => " + rating);
        }

        // remove lists with low ratings
        LOG.debug("Remove skill lists with low rating");

        ratedSkillListTitles.stream()
                .filter(r -> r.getInt() <= 100)
                .forEach(ratedSkillLists::remove);

        return ratedSkillLists;
    }

    /**
     * Extracts Lists of skills by checking the HTML List elements from given job offer and creates a Map with the title
     * of the skill list as the key and the List of skills as the value.
     *
     * @param jobOffer Job offer to be parsed
     * @return Map of skill Lists and their titles
     */
    private Map<IntStringPair, List<String>> extractSkillListsByHtmlTags(JobOffer jobOffer) {
        Map<IntStringPair, List<String>> ratedSkillLists = new HashMap<>();

        // get html list elements from body
        Elements listElements = getListElements(jobOffer.getBodyElement());

        for (Element listElement : listElements) {
            // get child list item elements
            Elements listItems = listElement.getElementsByTag("li");

            // get list title
            String listTitle = getListTitle(jobOffer, listItems);

            if (listTitle == null) {
                continue;
            }

            int rating = 100 + calcHtmlSkillListItemsRating(listItems);

            List<String> skills = new ArrayList<>();
            for (Element listItem : listItems) {
                skills.add(listItem.text());
            }

            IntStringPair ratedSkillListTitle = new IntStringPair(rating, listTitle);
            ratedSkillLists.put(ratedSkillListTitle, skills);
        }

        return ratedSkillLists;
    }

    /**
     * Extracts Lists of skills by checking for plain text lists of given job offer and creates a Map with the title of
     * the skill list as the key and the List of skills as the value.
     *
     * @param jobOffer Job offer to be parsed
     * @return Map of skill Lists and their titles
     */
    private Map<IntStringPair, List<String>> extractSkillListsByPattern(JobOffer jobOffer) {
        Map<IntStringPair, List<String>> ratedSkillLists = new HashMap<>();

        // Find non valid html lists
        String lastBulletPoint = null;
        String lastLine = null;
        String lastListTitle = null;
        List<String> lastListItems = new ArrayList<>();
        String[] lines = jobOffer.getPlainText().split("\\n");
        for (String line : lines) {
            line = line.trim();

            boolean addSkillList = false;

            if (line.isEmpty()) {
                if (lastListTitle != null) {
                    addSkillList = true;
                }
            } else {
                // check for potential list
                Matcher matcher = Pattern.compile("^([^a-zA-ZäöüÄÖÜ])\\s+.*$").matcher(line);
                if (matcher.find()) {
                    String bulletPoint = matcher.group(1);

                    if (lastBulletPoint == null) {
                        // first list item
                        lastBulletPoint = bulletPoint;
                        lastListTitle = lastLine;

                        line = line.substring(1, line.length()).trim();
                        lastListItems.add(line);

                    } else if (!bulletPoint.equals(lastBulletPoint)) {
                        if (lastListTitle != null) {
                            addSkillList = true;
                        }
                    } else if (bulletPoint.equals(lastBulletPoint)) {
                        // additional list item
                        line = line.substring(1, line.length()).trim();
                        lastListItems.add(line);

                    }
                } else {
                    if (lastListTitle != null) {
                        addSkillList = true;
                    }
                }
            }

            if (addSkillList) {
                IntStringPair ratedSkillListTitle = new IntStringPair(100, lastListTitle);
                ratedSkillLists.put(ratedSkillListTitle, lastListItems);
                lastListItems = new ArrayList<>();

                lastListTitle = null;
                lastBulletPoint = null;
            }

            // keep last non empty line
            lastLine = line;
        }

        return ratedSkillLists;
    }

    /**
     * Extracts Lists of skills by checking for potential skill list titles in plaint text of given job offer and
     * creates a Map with the title of the skill list as the key and the List of skills as the value.
     *
     * @param jobOffer Job offer to be parsed
     * @return Map of skill Lists and their titles
     */
    private Map<IntStringPair, List<String>> extractSkillListsBySentenceAnalyzing(JobOffer jobOffer) {
        Map<IntStringPair, List<String>> skillLists = new HashMap<>();

        String[] lines = jobOffer.getPlainText().split("\n");
        IntStringPair lastTitle = null;
        boolean parsingSkills = false;
        for (String line : lines) {
            if (line.trim().isEmpty()) {
                if (parsingSkills) {
                    List<String> skillList = skillLists.get(lastTitle);
                    if (!skillList.isEmpty()) {
                        parsingSkills = false;
                    }
                }
                continue;
            }

            if (parsingSkills) {
                List<String> skillList = skillLists.get(lastTitle);
                if (skillList != null) {
                    skillList.add(line);
                }
            }

            int nofWords = line.split("\\s").length;
            if (nofWords > 6) {
                // ignore lines with many words
                continue;
            }

            int rating = calcSkillListTitleRating(jobOffer, line);
            if (rating > 0) {
                parsingSkills = true;
                lastTitle = new IntStringPair(0, line);
                skillLists.put(lastTitle, new ArrayList<>());
            }

        }
        return skillLists;
    }

    /**
     * Extracts HTML list elements from given body element.
     *
     * @param body Body element to be extracted from
     * @return Extracted list elements
     */
    private Elements getListElements(Element body) {
        Elements listElements = new Elements();

        // add ul elements
        listElements.addAll(body.getElementsByTag("ul"));

        // add ol elements
        listElements.addAll(body.getElementsByTag("ol"));

        return listElements;
    }

    /**
     * Calculates skill list rating of given list.
     *
     * @param listItems List to be rated.
     * @return Calculated rating
     */
    private int calcHtmlSkillListItemsRating(Elements listItems) {
        double probability = 0;
        int nofListItems = listItems.size();
        for (Element listItem : listItems) {
            // adjust rating based on types of children
            if (containsSuspiciousChildren(listItem)) {
                probability -= 75d / nofListItems;
            }

            // adjust rating based on number of children (incl. children of children)
            int allChildCount = getAllChildCount(listItem);
            if (allChildCount > 3) {
                double subtract = (5d / nofListItems);
                subtract *= (allChildCount - 3);
                if (subtract > (25d / nofListItems)) {
                    subtract = (25d / nofListItems);
                }
                probability -= subtract;
            }
        }

        return (int) probability;
    }

    /**
     * Calculates skill list rating.
     *
     * @param jobOffer       Job offer object that will be used for the calculation
     * @param skillListTitle Title of the skill list to be rated
     * @param skills         List of skills to be rated
     * @return Calculated rating
     */
    private int calcSkillListRating(JobOffer jobOffer, String skillListTitle, List<String> skills) {
        double rating = 0;
        int nofListItems = skills.size();

        // adjust rating based on number of list items
        if (nofListItems == 0) {
            return 0;
        } else if (nofListItems == 1) {
            rating -= 25;
        } else if (nofListItems == 2) {
            rating -= 15;
        }

        // adjust rating based on number of special chars
        for (String skill : skills) {
            int nofSpecialChars = getNumberOfSpecialChars(skill);
            if (nofSpecialChars > skill.length() / 4d) {
                double subtract = 75d / nofListItems;
                subtract *= (double) nofSpecialChars / skill.length();
                rating -= subtract;
            }
        }

        // adjust rating based on list title ratings
        rating += calcSkillListTitleRating(jobOffer, skillListTitle);
        return (int) rating;
    }

    /**
     * Calculates rating of the skill list title.
     *
     * @param jobOffer Job offer element to be used for calculations
     * @param title    Title of skill list to be rated
     * @return Calculated rating
     */
    private int calcSkillListTitleRating(JobOffer jobOffer, String title) {
        // check if title is in suspicious element
        String regexSafeTitle = Pattern.quote(title);
        Elements titleElements = jobOffer.getDocument().getElementsMatchingOwnText(regexSafeTitle);
        for (Element element : titleElements) {
            String tagName = element.tagName();
            if (tagName.equalsIgnoreCase("a")
                    || tagName.equalsIgnoreCase("input")
                    || tagName.equalsIgnoreCase("button")) {
                return -15;
            }
        }

        int rating = 0;

        // adjust rating by number of words in title
        int nofWords = title.split("\\s").length;
        if (nofWords > 6) {
            rating -= nofWords * 5;
        }

        List<CoreMap> annotatedSentences = NlpHelper.getInstance().getAnnotatedSentences(title);
        for (CoreMap annotatedSentence : annotatedSentences) {
            SemanticGraph semanticGraph = annotatedSentence.get(SemanticGraphCoreAnnotations.BasicDependenciesAnnotation.class);
            Collection<TypedDependency> typedDependencies = semanticGraph.typedDependencies();
            if (typedDependencies.size() == 1) {
                for (TypedDependency typedDependency : typedDependencies) {
                    rating += calcSingleWordTitleDependencyRating(typedDependency);
                }

            } else {
                for (TypedDependency typedDependency : typedDependencies) {
                    rating += calcTitleDependencyRating(typedDependency);
                }
            }

        }

        return rating;
    }

    /**
     * Calculates rating of given {@link TypedDependency} that is a part of a skill list title. Rating calculation is
     * based on grammatical type of the word and the grammatical type of the dependency word and their meaning.
     *
     * @param dependency {@link TypedDependency} to be rated
     * @return Calculated rating
     */
    private int calcTitleDependencyRating(TypedDependency dependency) {
        String shortName = dependency.reln().getShortName();
        String word = dependency.dep().backingLabel().value().toLowerCase();

        IndexedWord gov = dependency.gov();
        String govTag = gov.tag();
        String govWord = gov.backingLabel().value().toLowerCase();

        if (EnglishGrammaticalRelations.DETERMINER.getShortName().equals(shortName)
                && "NN".equals(govTag)) {
            if (SkillExtractorConstants.DETERMINERS_YOUR.contains(word)) {
                if (wordContainsListItem(SkillExtractorConstants.NOUNS_SKILL_SYNONYM, govWord)) {
                    return 25;
                } else if (wordContainsListItem(SkillExtractorConstants.NOUNS_JOB_SYNONYM, govWord)) {
                    return -25;
                } else if (wordContainsListItem(SkillExtractorConstants.NOUNS_POSSIBILITY_SYNONYM, govWord)) {
                    return -25;
                }
            } else if (SkillExtractorConstants.DETERMINERS_OUR.contains(word)) {
                if (wordContainsListItem(SkillExtractorConstants.NOUNS_EXPECTATION_SYNONYM, govWord)) {
                    return 25;
                } else if (wordContainsListItem(SkillExtractorConstants.NOUNS_OFFER_SYNONYM, govWord)) {
                    return -25;
                }
            }
        } else if ((EnglishGrammaticalRelations.NOMINAL_SUBJECT.getShortName().equals(shortName) ||
                EnglishGrammaticalRelations.DIRECT_OBJECT.getShortName().equals(shortName)) &&
                "VVFIN".equals(govTag)) {
            if (SkillExtractorConstants.SUBJECTS_YOU.contains(word)) {
                if (SkillExtractorConstants.VERBS_OFFER.contains(govWord)) {
                    return 50;
                } else if (SkillExtractorConstants.VERBS_EXPECT.contains(govWord)) {
                    return -50;
                }
            } else if (SkillExtractorConstants.SUBJECTS_WE.contains(word)) {
                if (SkillExtractorConstants.VERBS_EXPECT.contains(govWord)) {
                    return 50;
                } else if (SkillExtractorConstants.VERBS_OFFER.contains(govWord)) {
                    return -50;
                }
            }
        } else if ((EnglishGrammaticalRelations.PUNCTUATION.getShortName().equals(shortName) ||
                "root".equals(shortName))
                && "NN".equals(govTag)) {
            if (wordContainsListItem(SkillExtractorConstants.NOUNS_SKILL_SYNONYM, govWord)) {
                return 25;
            } else if (wordContainsListItem(SkillExtractorConstants.NOUNS_EXPECTATION_SYNONYM, govWord)) {
                return 25;
            } else if (wordContainsListItem(SkillExtractorConstants.NOUNS_JOB_SYNONYM, govWord)) {
                return -35;
            } else if (wordContainsListItem(SkillExtractorConstants.NOUNS_OFFER_SYNONYM, govWord)) {
                return -35;
            } else if (wordContainsListItem(SkillExtractorConstants.NOUNS_POSSIBILITY_SYNONYM, govWord)) {
                return -35;
            }
        }

        return 0;
    }

    /**
     * Calculates rating of single word skill list title. Rating is based on grammatical type of the word.
     *
     * @param dependency {@link TypedDependency} of the word to be rated
     * @return Calculated rating
     */
    private int calcSingleWordTitleDependencyRating(TypedDependency dependency) {
        String tag = dependency.dep().tag();
        String word = dependency.dep().backingLabel().value().toLowerCase();

        if ("NN".equals(tag)) {
            if (wordContainsListItem(SkillExtractorConstants.NOUNS_SKILL_SYNONYM, word)) {
                return 25;
            } else if (wordContainsListItem(SkillExtractorConstants.NOUNS_EXPECTATION_SYNONYM, word)) {
                return 25;
            } else if (wordContainsListItem(SkillExtractorConstants.NOUNS_JOB_SYNONYM, word)) {
                return -35;
            } else if (wordContainsListItem(SkillExtractorConstants.NOUNS_OFFER_SYNONYM, word)) {
                return -35;
            } else if (wordContainsListItem(SkillExtractorConstants.NOUNS_POSSIBILITY_SYNONYM, word)) {
                return -35;
            }
        }
        return 0;
    }

    /**
     * Checks whether the given term contains an entry of the given List.
     *
     * @param list List of strings to be checked
     * @param term String that might contain a word of the list
     * @return <code>true</code> if the term contains an list entry, <code>false</code> otherwise
     */
    private boolean wordContainsListItem(List<String> list, String term) {
        for (String listItem : list) {
            if (term.contains(listItem)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Extracts title of the given List from the given job offer.
     *
     * @param jobOffer  Job offer object to be analysed
     * @param listItems List whose title will be extracted
     * @return Extracted list title or null if nothing found
     */
    private String getListTitle(JobOffer jobOffer, Elements listItems) {
        String firstListText = null;
        for (Element listItem : listItems) {
            firstListText = HtmlUtils.getPlainTextFromHtml(listItem.html()).trim();
            firstListText = getLastLine(firstListText);
            if (firstListText != null) {
                break;
            }
        }

        if (firstListText == null) {
            return null;
        }

        String jobOfferText = jobOffer.getPlainText();
        int firstListItemIndex = jobOfferText.indexOf(firstListText);
        String listTitle = jobOfferText.substring(0, firstListItemIndex);
        return getLastLine(listTitle);
    }

    /**
     * Counts number of special characters in given text.
     *
     * @param text Text to be analysed
     * @return Number of special characters
     */
    private int getNumberOfSpecialChars(String text) {
        Matcher specialCharMatcher = Pattern.compile(SkillExtractorConstants.SPECIAL_CHARACTER_REGEX).matcher(text);
        int specialCharCounter = 0;
        while (specialCharMatcher.find()) {
            specialCharCounter++;
        }
        return specialCharCounter;
    }

    /**
     * Checks whether the given potential skill list element contains suspicious HTML elements that should not be in a
     * skill list element.
     *
     * @param listItem Skill list element to be checked
     * @return <code>true</code> if the element contains suspicious elements, <code>false</code> otherwise
     */
    private boolean containsSuspiciousChildren(Element listItem) {
        return listItem.getElementsByTag("a").size() > 0
                || listItem.getElementsByTag("input").size() > 0
                || listItem.getElementsByTag("button").size() > 0;
    }

    /**
     * Counts number of child elements in given element. Children of children are also included.
     *
     * @param element Element to be analysed
     * @return Number of child elements
     */
    private int getAllChildCount(Element element) {
        int childCounter = 0;
        for (Element child : element.children()) {
            childCounter++;
            childCounter += getAllChildCount(child);
        }
        return childCounter;
    }

    /**
     * Extract last line of given text.
     *
     * @param text Text to be extracted from
     * @return Extracted last line or null if nothing found
     */
    private String getLastLine(String text) {
        text = text.trim();
        String[] lines = text.split("\n");
        for (int i = lines.length - 1; i >= 0; i--) {
            String line = lines[i];
            line = line.trim();
            if (!line.isEmpty()) {
                return line;
            }
        }
        return null;
    }

    /**
     * Creates a single String of the given skill List to be used as the return value of the {@link #parse(JobOffer)}
     * method.
     *
     * @param skills List of skills to be formatted to a single String
     * @return Single String of skills
     */
    private String generateSkillListPrintout(Collection<String> skills) {
        boolean isFirstLine = true;
        StringBuilder sbSkills = new StringBuilder();
        for (String skill : skills) {
            if (!isFirstLine) {
                sbSkills.append(SkillExtractorConstants.SEPARATOR);
            }
            sbSkills.append(skill);
            isFirstLine = false;
        }

        return sbSkills.toString();
    }
}


text:
import cv2 as cv
import matplotlib.pyplot as plt
import pickle
import sys

from heuristicSearch.envs.occupancy_grid import OccupancyGrid

clickedR, clickedC = -1, -1
def inputClickedPoint(image):
    """Displays an environment and tells you the row and column number of a
    clicked point in the map."""
    def clickCallback(event, x, y, flags, param):
        global clickedR, clickedC
        if event == cv.EVENT_LBUTTONDOWN:
            clickedC, clickedR = (x, y)

    cv.namedWindow("image")
    cv.setMouseCallback("image", clickCallback)
    cv.imshow("image", image)
    cv.waitKey(0)
    cv.destroyAllWindows()
    return (clickedR, clickedC)

def pointToRC(point):
    pointAsRC = (point[1], point[0])
    return pointAsRC

def plotStuff(planHValues, planTimePerState, stateHValues, planNodeIds=None,
        stateNodeIds=None):
    plt.figure(1)
    plt.subplot(311)
    if planNodeIds is None:
        plt.plot(planHValues)
    else:
        plt.plot(planNodeIds, planHValues)

    plt.subplot(312)
    if planNodeIds is None:
        plt.plot(planTimePerState)
    else:
        plt.plot(planNodeIds, planTimePerState)

    plt.subplot(313)
    if stateNodeIds is None:
        plt.plot(stateHValues)
    else:
        plt.plot(stateNodeIds, stateHValues)
    plt.show()

def euclideanDistance( a, b ):
    """Assumes inputs are tuples."""
    return ( ( a[0] - b[0] )**2 + ( a[1] - b[1] )**2 )**.5

def inputPoints( numPoints, occMap ):
    points = []
    for i in range(numPoints):
        print("Click on an point")
        point = inputClickedPoint(occMap)
        points.append(point)
    return points

def savePoints(points, fileName):
    pickle.dump( points, open(fileName, "wb") )

redpajama_set_name: RedPajamaGithub


text:
---
title: grunt-frontmatter
source: "https://github.com/drpicox/grunt-frontmatter"
website: "http://drpicox.github.io/grunt-frontmatter"
image: http://tomgurney.co.uk/wp-content/uploads/2015/10/Grunt-Logo.png
image_width: 900
image_height: 900
description: >
  A grunt task able to extract YAML front-matter
  from files and integrate all into a single JSON file.
tags:
  - projects
  - javascript
  - node
  - yaml
  - front-matter
  - grunt
  - jekyll
  - assemble

---

* replace with ToC
{:toc}

## Overview

This is a grunt task able to generate JSON data from
[front-matter](./front-matter) metadata
present in multiple files.

As example, given the following directory structure:

    .
    ├── Gruntfile.coffee
    ├── package.json
    └── source
        ├── articles
        │   ├── bellflower.md    <--
        │   ├── fiddler.html     <--
        │   └── healthy.md       <--
        ├── index.html
        ├── styles.css
        └── app.js

it can generate `articles.json` file as follows:

    .
    ├── Gruntfile.coffee
    ├── package.json
    ├── source
    └── release
        └── articles.json        <--

## Setup

Install it in your project with npm:

```bash
$ npm install --save-dev grunt-frontmatter
```

After it configure your _Gruntfile.js_ as follows:

```javascript
/** Gruntfile.js */
module.exports = function(grunt) {

  // Project tasks configurations
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json')

    // (C) Tasks configurations here
    frontmatter: {
        options: {
            minify: true,
            width: 200,
        },
        files: {
            'release/articles.json': ['source/articles/*.md']
        },
    }
  });

  // (L) Load here grunt plugins with tasks
  grunt.loadNpmTasks('grunt-frontmatter');

  // (T) Add here your task(s)
  grunt.registerTask('default', [ ... ]);
};
```

It should reproduce the example shown in the overview.


text:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="edu.kit.tm.pseprak2.alushare">

    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
    <uses-permission android:name="android.permission.READ_PROFILE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />

    <uses-feature
        android:name="android.hardware.camera"
        android:required="true" />

    <application
        android:name=".AluShare"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme"
        >
        <activity
            android:name=".view.SplashScreen"
            android:label="@string/title_activity_main"
            android:noHistory="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".view.MainActivity"
            android:configChanges="orientation|screenSize"
            android:label="@string/title_activity_main">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
        <activity
            android:name=".view.PersonalInfoActivity"
            android:configChanges="orientation|screenSize"
            android:label="@string/title_activity_personal_info"></activity>
        <activity
            android:name=".view.ChatActivity"
            android:configChanges="orientation|screenSize"
            android:label="@string/title_activity_chat"
            android:windowSoftInputMode="adjustResize">
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="edu.kit.tm.pseprak2.alushare.view.MainActivity" />
        </activity>
        <activity
            android:name=".view.CreateContactActivity"
            android:configChanges="orientation|screenSize"
            android:excludeFromRecents="true"
            android:label="@string/title_activity_create_contact"
            android:theme="@style/DialogTheme" />

        <service android:name=".network.NetworkingService" />

        <activity
            android:name=".view.ChooseContactActivity"
            android:label="@string/title_activity_choose_contact" />

        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="edu.kit.tm.pseprak2.alushare.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/fileprovider" />
        </provider>

        <activity

            android:name=".view.Preferences"
            android:label="@string/title_activity_preferences"></activity>
        <activity
            android:name="org.acra.CrashReportDialog"
            android:excludeFromRecents="true"
            android:finishOnTaskLaunch="true"
            android:launchMode="singleInstance"
            android:process=":error_report"
            android:theme="@style/DialogTheme" />
        <activity
            android:name=".view.TutorialActivity"
            android:label="@string/title_activity_tutorial"
            android:noHistory="true"
            android:theme="@style/AppTheme"/>
    </application>

</manifest>


text:
"""
Register an Axiom version plugin for Hyperbola.
"""

from zope.interface import directlyProvides
from twisted.plugin import IPlugin
from axiom.iaxiom import IVersion
from hyperbola import version
directlyProvides(version, IPlugin, IVersion)


text:
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import ListSubheader from '@material-ui/core/ListSubheader';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import Collapse from '@material-ui/core/Collapse';
import InboxIcon from '@material-ui/icons/MoveToInbox';
import DraftsIcon from '@material-ui/icons/Drafts';
import SendIcon from '@material-ui/icons/Send';
import ExpandLess from '@material-ui/icons/ExpandLess';
import ExpandMore from '@material-ui/icons/ExpandMore';
import StarBorder from '@material-ui/icons/StarBorder';

const useStyles = makeStyles(theme => ({
  root: {
    width: '100%',
    maxWidth: 360,
    backgroundColor: theme.palette.background.paper,
  },
  nested: {
    paddingLeft: theme.spacing(4),
  },
}));

export default function NestedList() {
  const classes = useStyles();
  const [open, setOpen] = React.useState(true);

  const handleClick = () => {
    setOpen(!open);
  };

  return (
    <List
      component="nav"
      aria-labelledby="nested-list-subheader"
      subheader={
        <ListSubheader component="div" id="nested-list-subheader">
          Nested List Items
        </ListSubheader>
      }
      className={classes.root}
    >
      <ListItem button>
        <ListItemIcon>
          <SendIcon />
        </ListItemIcon>
        <ListItemText primary="Sent mail" />
      </ListItem>
      <ListItem button>
        <ListItemIcon>
          <DraftsIcon />
        </ListItemIcon>
        <ListItemText primary="Drafts" />
      </ListItem>
      <ListItem button onClick={handleClick}>
        <ListItemIcon>
          <InboxIcon />
        </ListItemIcon>
        <ListItemText primary="Inbox" />
        {open ? <ExpandLess /> : <ExpandMore />}
      </ListItem>
      <Collapse in={open} timeout="auto" unmountOnExit>
        <List component="div" disablePadding>
          <ListItem button className={classes.nested}>
            <ListItemIcon>
              <StarBorder />
            </ListItemIcon>
            <ListItemText primary="Starred" />
          </ListItem>
        </List>
      </Collapse>
    </List>
  );
}


text:
package com.intellij.psi.search;

import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiReferenceService;
import com.intellij.psi.ReferenceRange;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;

/**
 * @author peter
 */
public final class SingleTargetRequestResultProcessor extends RequestResultProcessor {
  private static final PsiReferenceService ourReferenceService = PsiReferenceService.getService();
  private final PsiElement myTarget;

  public SingleTargetRequestResultProcessor(@NotNull PsiElement target) {
    super(target);
    myTarget = target;
  }

  public boolean processTextOccurrence(PsiElement element, int offsetInElement, final Processor<PsiReference> consumer) {
    for (PsiReference ref : ourReferenceService.getReferences(element, new PsiReferenceService.Hints(myTarget, offsetInElement))) {
      if (ReferenceRange.containsOffsetInElement(ref, offsetInElement)) {
        if (ref.isReferenceTo(myTarget)) {
          if (!consumer.process(ref)) {
            return false;
          }
        }
      }
    }
    return true;
  }

  @Override
  public String toString() {
    return "SingleTarget: " + myTarget;
  }
}


text:
/*
 * parse_link_header()
 *
 * Parse the Github Link HTTP header used for pageination
 * http://developer.github.com/v3/#pagination
 */
export default function parse_link_header(header) {
  if (header.length === 0) {
    throw new Error("input must not be of zero length");
  }

  // Split parts by comma
  var parts = header.split(',');
  var links = {};
  // Parse each part into a named link
  parts.forEach(function(p) {
    var section = p.split(';');
    if (section.length !== 2) {
      throw new Error("section could not be split on ';'");
    }
    var url = section[0].replace(/<(.*)>/, '$1').trim();
    var name = section[1].replace(/rel="(.*)"/, '$1').trim();
    links[name] = url;
  });

  return links;
}


text:
/* $Id: tx_simulator.c 199 2014-10-21 14:25:02Z roca $ */
/*
 * OpenFEC.org AL-FEC Library.
 * (c) Copyright 2009-2011 INRIA - All rights reserved
 * Contact: vincent.roca@inria.fr
 *
 * This software is governed by the CeCILL-C license under French law and
 * abiding by the rules of distribution of free software.  You can  use,
 * modify and/ or redistribute the software under the terms of the CeCILL-C
 * license as circulated by CEA, CNRS and INRIA at the following URL
 * "http://www.cecill.info".
 *
 * As a counterpart to the access to the source code and  rights to copy,
 * modify and redistribute granted by the license, users are provided only
 * with a limited warranty  and the software's author,  the holder of the
 * economic rights,  and the successive licensors  have only  limited
 * liability.
 *
 * In this respect, the user's attention is drawn to the risks associated
 * with loading,  using,  modifying and/or developing or reproducing the
 * software by the user in light of its specific status of free software,
 * that may mean  that it is complicated to manipulate,  and  that  also
 * therefore means  that it is reserved for developers  and  experienced
 * professionals having in-depth computer knowledge. Users are therefore
 * encouraged to load and test the software's suitability as regards their
 * requirements in conditions enabling the security of their systems and/or
 * data to be ensured and,  more generally, to use and operate it in the
 * same conditions as regards security.
 *
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL-C license and that you accept its terms.
 */

#include "eperftool.h"

/*
 * Local functions
 */
static void	randomize_array (UINT32 *array, UINT32 array_len);

static UINT32	define_symbol_tx_order (UINT32	*array);

static bool*	create_loss_array_from_erasure_proba	(UINT32 size, double desired_loss_proba);

static bool*	create_loss_array_from_erasure_nb	(UINT32 size, UINT32 desired_loss_nb);

static bool*	create_loss_array_from_markov_model	(UINT32 size);

/** This table gives the order in which transmissions take place. */
static UINT32*	tx_order_tab = NULL;

/** This table indicates which of the symbols are lost. */
static bool*	is_lost_tab = NULL;

/** control the number of received symbols in find_min_overhead_mode. We need a counter for that. */
static UINT32	tot_nb_recvd_symbols;

/* This is the index for next symbol sent and perhaps received, unless it has been lost */
static UINT32	next_idx = 0;

/** PRNG state. */
static unsigned long next = 1;

void mysrand (UINT32 seed)
{
	next = seed;
}

/* RAND_MAX assumed to be 32767 */
UINT32 myrand ()
{
	next = next * 1103515245 + 12345;
	return(next & 0x7fffffff);
}

of_status_t
init_tx_simulator()
{
	UINT32		i;

	/* first of all, fix the seed */
	init_prng_with_seed(suggested_seed);
	/*
	 * Randomize the symbol order... This order is used for the "transmission" of symbols.
	 * It provides a list of indexes that can be used later to access the right
	 */
	if ((tx_order_tab = (UINT32*)calloc(tot_nb_encoding_symbols, sizeof(UINT32))) == NULL) {
		OF_PRINT_ERROR(("no mem\n"))
		goto error;
	}
	if ((max_decoding_steps = define_symbol_tx_order(tx_order_tab)) == 0) {
		OF_PRINT_ERROR(("ERROR, define_symbol_tx_order() failed\n"))
		goto error;
	}
	/*
	 * Create a loss array, that defines which of the symbols in the tx_order_tab are lost.
	 * This can be made either from the target erasure probability, or by giving an
	 * actual number of erasures. The loss model must also be considered during this
	 * process.
	 */
	switch (loss_model) {
	case 0:
		/* no loss */
		is_lost_tab = create_loss_array_from_erasure_nb(max_decoding_steps, 0);
		break;
	case 1:
		is_lost_tab = create_loss_array_from_markov_model(max_decoding_steps);
		break;
	case 2:
		is_lost_tab = create_loss_array_from_erasure_proba(max_decoding_steps, p_loss);
		break;
	case 3:
		if (tx_mode == TX_MODE_SIMUL_BCAST_WITH_UNICAST_REPAIR) {
			/* do things in two steps: loss array for the first repair symbols, then
			 * extend it to simulate the reception of all source symbols. */
			if (nb_loss > tot_nb_repair_symbols) {
				OF_PRINT_ERROR(("number of desired losses (%d) cannot exceed number of repair symbols (%d)\n",
						nb_loss, tot_nb_repair_symbols))
				goto error;
			}
			is_lost_tab = create_loss_array_from_erasure_nb(tot_nb_repair_symbols, nb_loss);
			for (i = 0; i < src_pkt_nb; i++) {	/* mark the following (source) symbols as received */
				is_lost_tab[tot_nb_repair_symbols + i] = false;
			}
		} else {
			if (nb_loss > max_decoding_steps) {
				OF_PRINT_ERROR(("number of desired losses (%d) cannot exceed total number of symbols that could be received (%d)\n",
						nb_loss, max_decoding_steps))
				goto error;
			}
			is_lost_tab = create_loss_array_from_erasure_nb(max_decoding_steps, nb_loss);
		}
		break;
	case 4:
		is_lost_tab = create_loss_array_from_erasure_nb(max_decoding_steps, 0);
		break;
	case 5:
		/* loss only occur after the first trim_after_this_nb_rx_pkts received packets */
		if (trim_after_this_nb_rx_pkts > max_decoding_steps) {
			OF_PRINT_ERROR(("number of symbols to receive (%d) cannot exceed total number of symbols that could be received (%d)\n",
					trim_after_this_nb_rx_pkts, max_decoding_steps))
			goto error;
		}
		is_lost_tab = create_loss_array_from_erasure_nb(max_decoding_steps, 0);
		for (i = trim_after_this_nb_rx_pkts; i < max_decoding_steps; i++) {
			is_lost_tab[i] = true;
		}
		break;
	default:
		OF_PRINT_ERROR(("loss model (%d) is not supported\n", loss_model))
		goto error;
	}
	/* reset the number of received symbol counter and next_idx counter (required to
	 * supportfind_min_overhead_mode) */
	tot_nb_recvd_symbols = 0;
	next_idx = 0;
	OF_TRACE_LVL(1, ("init_tx_simulator: %d symbols can be received\n", max_decoding_steps))
	return OF_STATUS_OK;

error:
	return OF_STATUS_ERROR;
}

of_status_t
close_tx_simulator ()
{
	if (ldpc_matrix_file_name)
	{
		free(ldpc_matrix_file_name);
		ldpc_matrix_file_name=NULL;
	}
	if (is_lost_tab) {
		free(is_lost_tab);
		is_lost_tab = NULL;
	}
	if (tx_order_tab) {
		free(tx_order_tab);
		tx_order_tab = NULL;
	}
	if (ldpc_matrix_file_name)
	{
		free(ldpc_matrix_file_name);
		ldpc_matrix_file_name=NULL;
	}
	return OF_STATUS_OK;
}

/**
 * Return the next symbol received or NULL if none is available.
 * It goes through the list of (permuted in a certain manner) symbols sent and applies
 * the desired loss model on top of it.
 */
symbol_cb_t *
get_next_symbol_received ()
{
	symbol_cb_t		*symb;

	while (next_idx < max_decoding_steps) {
		if (is_lost_tab[next_idx] == true) {
			/* this symbol is lost, switch to the next one */
			next_idx++;
			continue;
		} else {
			/* this symbol is received, return it */
			if ((find_min_overhead_mode == true) &&
			    (tot_nb_recvd_symbols >= trim_after_this_nb_rx_pkts)) {
				/* stop test in find_min_overhead mode if we achieved the maximum value */
				break;
			}
			tot_nb_recvd_symbols++;
			if (loss_model == 4)
			{
				symb = &(symb_cb_tab[tx_order_tab[myrand() % max_decoding_steps]]);
			}
			else
			{
				symb = &(symb_cb_tab[tx_order_tab[next_idx]]);
			}
			OF_TRACE_LVL(1, ("%s: next_idx: %u, tx_order_tab: %u, symb esi: %u, sbn: %u\n",
				__FUNCTION__, next_idx, tx_order_tab[next_idx], symb->esi, symb->sbn))
			next_idx++;
			return symb;
		}
	}
	OF_TRACE_LVL(1, ("%s: no symbol available any more after receiving %d symbols...\n",
			__FUNCTION__, tot_nb_recvd_symbols))
	return NULL;
}

/**
 * Randomize an array of integers
 */
void
randomize_array (UINT32		*array,
		 UINT32		array_len)
{
	UINT32	backup = 0;
	UINT32	rand_idx = 0;
	UINT32	i;

	for (i = 0; i < array_len; i++ ) {
		array[i] = i;
	}
	for (i = 0; i < array_len; i++) {
		backup = array[i];
		rand_idx = myrand() % array_len;
		array[i] = array[rand_idx];
		array[rand_idx] = backup;
	}
}

UINT32
define_symbol_tx_order (UINT32	*array)
{
	UINT32	max_steps;	// total number of packets received
	UINT32	i;

	switch (tx_mode) {
	case TX_MODE_ALL_RANDOM:		// random permutation of all symbols
		OF_TRACE_LVL(1, ("Randomly send all source + repair symbols...\n"))
		max_steps = tot_nb_encoding_symbols;
		randomize_array(array, max_steps);
		break;

	case TX_MODE_FEW_SRC_SYMBOLS: {	// all repair pkts + a few source packets
		UINT32	*rand_src_idx;	// tab of randomly sorted src pkt idx
		UINT32	nb_src_considered; // nb of source packets sent
		UINT32	offset;		// offset to add to all indexes
		UINT32	idx;		// packet index

		// src_pkt_ratio is the % of source data packets that are sent
		if (use_src_pkt_ratio) {
			nb_src_considered = (UINT32)((double)src_pkt_ratio / 100 * (double)tot_nb_source_symbols);
		} else {
			nb_src_considered = src_pkt_nb;
		}
		max_steps = tot_nb_repair_symbols + nb_src_considered;
		if ((rand_src_idx = (UINT32*)calloc(nb_src_considered, sizeof(int))) == NULL) {
			goto no_mem;
		}
		OF_TRACE_LVL(1, ("Randomly send %d source symbols (not necessarily received) and all the repair symbols in a random order...\n",
			nb_src_considered))
		randomize_array(rand_src_idx, nb_src_considered);
		randomize_array(array, max_steps);
		offset = tot_nb_encoding_symbols - max_steps;
		for (i = 0; i < max_steps; i++ ) {
			idx = array[i];
			if (idx < nb_src_considered) {
				// it's a source packet
				array[i] = rand_src_idx[idx];
			} else {
				// it's a repair packet
				array[i] += offset;
			}
		}
		free(rand_src_idx);
		break;
		}

	case TX_MODE_FEW_SRC_SYMBOLS_FIRST: {
					// all repair pkts + a few source packets
					// sent first to be sure they will be received
		UINT32	*rand_src_idx;	// tab of randomly sorted src pkt idx
		UINT32	nb_src_considered; // nb of source packets sent

		if (use_src_pkt_ratio) {
			nb_src_considered = (UINT32)((double)src_pkt_ratio / 100 * (double)tot_nb_source_symbols);
		} else {
			nb_src_considered = src_pkt_nb;
		}
		max_steps = tot_nb_repair_symbols + nb_src_considered;
		if ((rand_src_idx = (UINT32*)calloc(nb_src_considered, sizeof(UINT32))) == NULL) {
			goto no_mem;
		}
		OF_TRACE_LVL(1, ("Randomly send %d source symbols first (always received), then randomly all repair symbols...\n",
			nb_src_considered))
		randomize_array(rand_src_idx, nb_src_considered);
		randomize_array(array + nb_src_considered, tot_nb_repair_symbols);
		for (i = 0; i < max_steps; i++) {
			if (i < nb_src_considered) {
				// it's a source packet
				array[i] = rand_src_idx[i];
			} else {
				// it's a repair packet
				array[i] += tot_nb_source_symbols;
			}
		}
		free(rand_src_idx);
		break;
		}

	case TX_MODE_NON_SYSTEMATIC:	// no source packet transmission
		OF_TRACE_LVL(1, ("Randomly send only repair symbols (non systematic)...\n"))
		max_steps = tot_nb_repair_symbols;
		randomize_array(array, max_steps);
		for (i = 0; i < max_steps; i++ ) {
			array[i] += tot_nb_source_symbols;
		}
		break;

	case TX_MODE_SEQUENTIAL:
		OF_TRACE_LVL(1, ("Sequentially send all source symbols first, then repair symbols...\n"))
		max_steps = tot_nb_encoding_symbols;
		for (i = 0; i < max_steps; i++ ) {
			array[i] = i;
		}
		break;

	case TX_MODE_INVERSE_SEQUENTIAL:
		OF_TRACE_LVL(1, ("Sequentially send all repair symbols first, then source symbols...\n"))
		max_steps = tot_nb_encoding_symbols;
		for (i = 0; i < max_steps; i++ ) {
			if (i < tot_nb_repair_symbols) {
				array[i] = i + tot_nb_source_symbols;
			} else {
				// it's a repair packet
				array[i] = i - tot_nb_repair_symbols;
			}
		}
		break;

	case TX_MODE_SEQUENTIAL_SRC_THEN_RANDOM_REPAIR:
		OF_TRACE_LVL(1, ("Sequentially send all source symbols first, then randomly repair symbols...\n"))
		max_steps = tot_nb_encoding_symbols;
		randomize_array(array + tot_nb_source_symbols, tot_nb_repair_symbols);
		for (i = 0; i < max_steps; i++ ) {
			if (i < tot_nb_source_symbols) {
				array[i] = i;
			} else {
				// it's a repair packet
				array[i] += tot_nb_source_symbols;
			}
		}
		break;

	case TX_MODE_SEQUENTIAL_REPAIR_THEN_RANDOM_SRC:
		OF_TRACE_LVL(1, ("Sequentially send all repair symbols first, then randomly source symbols...\n"))
		max_steps = tot_nb_encoding_symbols;
		randomize_array(array + tot_nb_repair_symbols, tot_nb_source_symbols);
		for (i = 0; i < max_steps; i++ ) {
			if (i < tot_nb_repair_symbols) {
				array[i] = i + tot_nb_source_symbols;
			}
		}
		break;

	case TX_MODE_SIMUL_BCAST_WITH_UNICAST_REPAIR: {
					// simulate ISDB-Tmm with unicast repair:
					// send all repair randomly, subject to packet
					// losses, then send the first few source packets
					// sequentially, not subject to any loss (3G connection)
		UINT32	*src_idx;	// tab of src pkt idx
		UINT32	nb_src_considered; // nb of source packets sent
		UINT32	i;

		if (use_src_pkt_ratio) {
			//nb_src_considered = (UINT32)((double)src_pkt_ratio / 100 * (double)tot_nb_source_symbols);
			OF_PRINT_ERROR(("ERROR, use -rx_src_nb=<n> to specify number of erasures in tx_mode TX_MODE_SIMUL_BCAST_WITH_UNICAST_REPAIR\n"))
			goto error;
		} else {
			nb_src_considered = src_pkt_nb;
		}
		max_steps = tot_nb_repair_symbols + nb_src_considered;
		if ((src_idx = (UINT32*)calloc(nb_src_considered, sizeof(UINT32))) == NULL) {
			goto no_mem;
		}
		OF_TRACE_LVL(1, ("simulate broadcast tx + unicast repair (send all repair randomly, subject to packet losses, then send the first %d source packets sequentially, not subject to any loss (3G connection)\n",
			nb_src_considered))
		for (i = 0; i < nb_src_considered; i++ ) {	// in sequence
			src_idx[i] = i;
		}
		randomize_array(array, tot_nb_repair_symbols);
		for (i = 0; i < max_steps; i++) {
			if (i < tot_nb_repair_symbols) {
				// it's a repair packet
				array[i] += tot_nb_source_symbols;
			} else {
				// it's a source packet
				array[i] = src_idx[i - tot_nb_repair_symbols];
			}
		}
		free(src_idx);
		break;
		}

#if 0
	case TX_MODE_PKT_INTERLEAVING:
		UINT32	j;
		OF_TRACE_LVL(1, ("Send source and repair symbol in an interleaved way...\n"))
		max_steps = tot_nb_encoding_symbols;
		for (i = 0; i < (UINT32)floor((double)bs.A_large * fec_ratio); i++ ) {
			UINT32	k = 0;
			UINT32	k_for_this_blk;
			UINT32	idx = i;
			UINT32	repair_idx = tot_nb_source_symbols;
			for (j = 0; j < (UINT32)bs.nb_blocks; j++ ) {
				if (j < (UINT32)bs.I) {
					k_for_this_blk = bs.A_large;
				} else {
					k_for_this_blk = bs.A_small;
				}
				if (i < k_for_this_blk) {
					array[k] = idx; /* source */
					printf("k=%i,array[%i]=%i\n",k,k,array[k]);
					k++;
				} else if (i < (UINT32)floor((double)k_for_this_blk * fec_ratio)) {
					array[k] = repair_idx + (i - k_for_this_blk); /* repair */
					printf("k=%i,array[%i]=%i\n",k,k,array[k]);
					k++;
				}
				idx += k_for_this_blk;
				repair_idx += (UINT32)floor((double)k_for_this_blk * fec_ratio) - k_for_this_blk;
			}
		}
		break;
#endif
	default:
		OF_PRINT_ERROR(("ERROR: transmission mode %d not supported!\n", tx_mode))
		goto error;
	}
	return max_steps;

no_mem:
	OF_PRINT_ERROR(("ERROR: no memory.\n"))
error:
	return 0;
}

/**
 * Simulate packets losses randomly using a simple two state Markov model.
 * @return	Returns 0 if OK, 1 if packet should be lost.
 */
int	random_loss(void)
{
	static UINT32	state = 0;	/* loss state in the Markov model: 0: NO_LOSS,  1: LOSS */
	UINT32		is_lost = 0;

	switch (state) {
	case 0: /* last packet was sent OK. */
		if (((double)myrand() * 100.0 / (double)RAND_MAX) < (double)p_loss_when_ok) {
			is_lost = 1;
			state = 1;
		}
		break;
	case 1: /* last packet was lost */
		if (((double)myrand() * 100.0 / (double)RAND_MAX) < (double)p_success_when_losses) {
			state = 0;
		} else {
			is_lost = 1;
		}
		break;
	default:
		OF_PRINT_ERROR(("random_loss: unknown state"))
		exit(-1);
	}
	if (is_lost)
		tx_simul_loss++;
	return is_lost;
}

/**
 * simulate random losses using the markov model
 */
bool*
create_loss_array_from_markov_model(UINT32 size)
{
	bool*	is_lost_array;		/* array that will designate the erasures */
	UINT32	i;

	is_lost_array = (bool*) calloc(size, sizeof(bool));
	for (i = 0; i < size; i++)
	{
		if (random_loss() == 1)
			is_lost_array[i] = true;
	}
	return is_lost_array;
}

/**
 * Choose randomly desired_loss_nb "1s" in an array of the given size and allocated by this
 * function.
 */
bool*
create_loss_array_from_erasure_nb (UINT32	size,
				   UINT32	desired_loss_nb)
{
	bool*	is_lost_array;		/* array that will designate the erasures */
	UINT32	actual_loss_nb;
	UINT32	i;
	UINT32	j;

	is_lost_array = (bool*) calloc(size, sizeof(bool));
	actual_loss_nb = 0;
	for (i = 0; i < desired_loss_nb; i++) {
		do {
			j = myrand() % size;
		} while (is_lost_array[j] == true);
		actual_loss_nb++;
		is_lost_array[j] = true;
	}
	if (actual_loss_nb != desired_loss_nb) {
		OF_PRINT_ERROR(("create_loss_arry_from_erasure_nb: WARNING actual_loss_nb (%d) != desired_loss_nb (%d)\n",
				actual_loss_nb, desired_loss_nb))
	}
	return is_lost_array;
}

/**
 * Choose randomly a number of "1s" corresponding to the desired loss probability in an array
 * of the given size and allocated by this function.
 */
bool*
create_loss_array_from_erasure_proba (UINT32	size,
				      double	desired_loss_proba)
{
	bool	*array;	/* array that will designate the erasures */
	UINT32	desired_loss_nb;
	UINT32	actual_loss_nb;
	UINT32	i;
	UINT32	j;

	array = (bool*) calloc(size, sizeof(bool));
	desired_loss_nb = (UINT32)((double)size * desired_loss_proba / 100.0);
	actual_loss_nb = 0;
	for (i = 0; i < desired_loss_nb; i++) {
		do {
			j = myrand() % size;
		} while (array[j] != 0);
		actual_loss_nb++;
		array[j] = 1;
	}
	if (actual_loss_nb != desired_loss_nb) {
		OF_PRINT_ERROR(("create_loss_arry_from_erasure_nb: WARNING actual_loss_nb (%d) != desired_loss_nb (%d)\n",
				actual_loss_nb, desired_loss_nb))
	}
	return array;
}

#if 0
int
loss_oracle (double	p)
{
	double	r;

	r = ((double)myrand() / (double)RAND_MAX);
	if (r < p)
		return 1;	/* lost */
	else
		return 0;	/* not lost */

	return is_lost;
}
#endif

/**
 * Initialize the Pseudo-random number generator with a random seed.
 */
of_status_t
init_prng_with_seed (UINT32	suggested_seed)
{
	UINT32	seed = 0;	/* random seed for the mysrand() function */

	if (suggested_seed != 0) {
		seed = suggested_seed;
	} else {
		/* determine our own random seed */
#ifdef WIN32
		seed = timeGetTime();
#else  /* UNIX */
		/*
		 * the use of /dev/random is safer than urandom but can be a blocking call if the
		 * entropy pool is empty ... so with urandom we often have a value ...
		 * char* dev_random_path="/dev/random";
		 */
		char* dev_random_path = "/dev/urandom";
		FILE* dev_random;
		if ((dev_random = fopen(dev_random_path, "r"))) {
			fread(&seed, sizeof(int), 1, dev_random);
			OF_TRACE_LVL(1,("init_prng_with_seed: getting the seed %d from /dev/urandom\n", seed));
			fclose(dev_random);
		} else {
			/* /dev/random is not available so we take usec as random number generator*/
			struct timeval	tv;
			if (gettimeofday(&tv, NULL) < 0) {
				OF_PRINT_ERROR(("init_prng_with_seed: ERROR, gettimeofday() failed:"))
				return OF_STATUS_ERROR;
			}
			seed = (int)tv.tv_usec;
		}
#endif /* OS */
	}
	mysrand(seed);
	OF_PRINT(("prng seed=%u\n", seed))
	return OF_STATUS_OK;
}

#if 0
//#ifdef DEBUG
int
count_received_pkts (block_t	*blk,
		     packet_t	*pkt,
		     char**	dataDest)
{
	UINT32	count1 = 0;
	UINT32	count2 = 0;
	UINT32	i;

	// check there are indeed that number of received pkts
	for (i = blk->first_pkt_idx;
	     i < blk->first_pkt_idx + blk->k;
	     i++) {
		if (dataDest[i] == NULL) {
			/* not received */
			continue;
		}
		/* received */
		count1++;
	}
	for (i = blk->first_repair_pkt_idx;
	     i < blk->first_repair_pkt_idx + blk->n - blk->k;
	     i++) {
		if (dataDest[i] == NULL) {
			/* not received */
			continue;
		}
		/* received */
		count2++;
	}
	OF_TRACE_LVL(2, ("BLOCK seq=%d: k/n=(%d/%d), pkt_rx=%d\n\tDATA recvd=%d, REPAIR recvd=%d\n",
		pkt->blk_seq, blk->k, blk->n, blk->pkt_rx, count1, count2))
	return (count1+count2);
}
#endif // DEBUG

#ifdef OF_DEBUG
/*
 * Warning, this function is not compatible with a normal use of eperftool...
 * Said differently, do not expect to be able to decode afterwards with the
 * standard receive_and_decode() function. Reason is that get_next_symbol_received
 * is not re-entrant.
 */
void
print_rx_stats (void)
{
	symbol_cb_t	*new_symb_cb;	/* pointer to the symbol just received */
	UINT32		nb_recvd = 0;
	UINT32		nb_lost  = 0;

	while ((new_symb_cb = get_next_symbol_received()) != NULL) {
		nb_recvd++;
		OF_TRACE_LVL(1, ("rx: \tsbn=%u    esi=%u\n", new_symb_cb->sbn, new_symb_cb->esi))
	}
	nb_lost = tot_nb_encoding_symbols - nb_recvd;
	OF_PRINT(("rx stats: %u recvd, %u lost\n", nb_recvd, nb_lost))
}
#endif // OF_DEBUG


text:
- [Cheat Sheet][cheatsheet]
- Getting Started
  - [Usage in Syncano Socket](#usage-in-syncano-socket)
  - [Installation](#installation)
- The Basics
  - [Data](/docs/basics/data.md)
  - [Users](/docs/basics/users.md)
  - [Responses](/docs/basics/responses.md)
  - [Endpoints](/docs/basics/endpoints.md)
  - [Channels](/docs/basics/channels.md)
  - [Events](/docs/basics/events.md)
  - [Logger](/docs/basics/logger.md)

-
  Architecture Concepts

  - [Socket](/docs/architecture/socket.md)*
  - [Socket Context](/docs/architecture/socket-context.md)*

-
  Syncano Core

  - [Syncano Account](/docs/core/syncano-account.md)*
  - [Syncano Backups](/docs/core/syncano-backups.md)*
  - [Syncano Classes](/docs/core/syncano-classes.md)*
  - [Syncano Hostings](/docs/core/syncano-hostings.md)*
  - [Syncano Instances](/docs/core/syncano-instances.md)*
  - [Syncano Sockets](/docs/core/syncano-sockets.md)*
  - [Syncano Traces](/docs/core/syncano-traces.md)*

`*` - TODO

## Usage in Syncano Socket

To learn about Syncano Sockets visit [documentation][socket].

```js
import Syncano from 'syncano-server'

export default async ctx => {
  // Initialize Syncano Server Library
  const {data, response} = new Syncano(ctx)

  // Check if user is authenticated
  if (!ctx.meta.user) {
    response.json({message: 'Unauthorized'}, 401)
    process.exit(0)
  }

  // Get user id from Socket Context
  const {id: author} = ctx.meta.user
  const {title} = ctx.args

  // Create post
  const post = await data.posts.create({title, author})

  // Respond with created post
  response.json(post)
}
```

## Installation

To install Syncano Server Library, use npm or yarn in your [socket][socket].

npm i syncano-server --save

[socket]: https://syncano.github.io/syncano-node-cli/#/using-sockets/overview
[cheatsheet]: https://cheatsheet.syncano.io/#server


text:
<?php
/*
    ALiVE 3D Rendering Engine Version 4 for PHP5
    File: world.php
    Description: World rendering file
    Developer: Dionyziz
*/

final class ALiVE_Universe {
    private $mView;
    private $mProjection;
    // objects contain preprocessed object data
    private $mObjects;
    // objects will be moved to points/polygons altogether after Build()
    private $mPoints; // world points after object transformations (3D vectors)
    private $mTransformedPoints; // $this->mPoints after world transformations (2D vectors)
    private $mPolygons;

    public function ALiVE_Universe() {
        $this->SetView(
            new ALiVE_Transformation_Neutral()
        ); // default view
        $this->SetProjection(
            new ALiVE_Projection_Isometric()
        ); // default projection
    }
    public function SetView( ALiVE_Transformation $view ) { // i.e. camera
        $this->mView = $view;
    }
    public function SetProjection( ALiVE_Projection $projection ) {
        $this->mProjection = $projection;
    }
    public function AddObject( ALiVE_Object $object ) {
        $this->mObjects[] = $object;
    }
    protected function Build() {
        $this->mPoints = array();
        $this->mPolygons = array();
        foreach ( $this->mObjects as $object ) {
            // apply object transformations (object scaling, object rotation, object translation)
            $object->Transform();
            $objectpoints = $object->GetTransformedPoints();
            // offset of first point of this object in world points array
            $objectoffset = count( $this->mPoints );
            foreach ( $objectpoints as $vector ) {
                $this->mPoints[] = $vector;
            }
            $objectpolygons = $object->GetPolygons();
            foreach ( $objectpolygons as $polygon ) { // $polygon is a copy
                // offset should change from $object->GetTransformedPoints() offset
                // to $this->mPoints offset
                w_assert( isset( $polygon[ 0 ] ) );
                w_assert( isset( $polygon[ 1 ] ) );
                w_assert( isset( $polygon[ 2 ] ) );
                w_assert( isset( $objectpoints[ $polygon[ 0 ] ] ) );
                w_assert( isset( $objectpoints[ $polygon[ 1 ] ] ) );
                w_assert( isset( $objectpoints[ $polygon[ 2 ] ] ) );
                $polygon[ 0 ] += $objectoffset;
                $polygon[ 1 ] += $objectoffset;
                $polygon[ 2 ] += $objectoffset;
                $this->mPolygons[] = $polygon;
            }
        }
    }
    public function GetTransformedPoints() {
        return $this->mTransformedPoints;
    }
    public function GetPolygons() {
        return $this->mPolygons;
    }
    public function Transform() {
        $this->Build();
        // apply world transformations
        // OPTIMIZABLE: TODO: Find a way to combine a normal transformation and a projection?
        //                    and be able to make ->Apply() return a 2D vector?
        $afterview = $this->mView->Apply( $this->mPoints );
        $this->mTransformedPoints = $this->mProjection->Apply( $afterview );
    }
}

?>


text:
package com.thinkgem.jeesite.modules.wx.web;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.thinkgem.jeesite.common.web.BaseController;
import com.thinkgem.jeesite.modules.wx.service.WxUserinfoService;
import com.thinkgem.jeesite.modules.wx.util.SignUtil;

import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
@Controller
@RequestMapping(value = "${frontPath}/wx")
public class CustomerController extends BaseController {

	@Autowired
    private WxMpService wxMpService;
	@Autowired
	private WxUserinfoService wxUserinfoService;
	/**
	 *
	 *

	 * Description:我的简介

	 *

	 * @author yubin
	 * @version 0.1 2016年4月27日
	 * @param code
	 * @param model
	 * @return
	 * String
	 */
	@RequestMapping(value = "userInfo")
	public String userInfo(String code, HttpServletRequest request,Model model) {
		WxMpUser wxMpUser=null;
		try {
		    //WxMpOAuth2AccessToken wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
		    //wxMpUser = wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, null);
		    //wxUserinfoService.saveUserInfo(wxMpUser);
		    model.addAttribute("jsapi", SignUtil.sign(wxMpService.getJsapiTicket(), request.getRequestURL().toString()));
		} catch (Exception e) {
			logger.error("我的简介",e);
		}
		model.addAttribute("wxMpUser", wxMpUser);
		return "modules/wx/userInfo";
	}
	@RequestMapping(value = "form")
	public String form(HttpServletRequest request,Model model){
	    try {
	    	Map<String, String> ret = SignUtil.sign(wxMpService.getJsapiTicket(), request.getRequestURL().toString());
		   model.addAttribute("jsapi", ret);
		} catch (WxErrorException e) {
			logger.error("微信js",e);
		}catch (Exception e) {
			logger.error("微信js",e);
		}
		return "modules/wx/form";
	}
}


text:
package com.tinycat.util;

import java.util.Random;

public class NameUtil {
	/**
	 * 产生随机姓名,3字,姓使用百家姓,越靠后概率越低,名依据性别选取
	 *
	 * @autor: wn 2014-8-15 上午11:36:16
	 * @param gender
	 * @return
	 */
	public static String getRandomName(boolean boy) {
		int girl_size = NameConstants.GIRL_NAME.length;
		int boy_size = NameConstants.BOY_NAME.length;
		int index = 0;
		String name = "";
		if(boy) {
			index = randomInt(0, boy_size-1);
			name = NameConstants.BOY_NAME[index];
		}else{
			index = randomInt(0, girl_size-1);
			name = NameConstants.GIRL_NAME[index];
		}
		return getRandomXing()+name;
	}

	/**
	 * 获取随机姓氏,从前向后概率依次降低
	 *
	 * @autor: wn 2014-8-15 下午12:13:39
	 * @return
	 */
	private static String getRandomXing() {
		int totalCount = NameConstants.XING.length;
		int index = randomInt(0, totalCount);
		if (index>totalCount/5)
			index = randomInt(0, totalCount);
		if (index>totalCount/4)
			index = randomInt(0, totalCount);
		if (index>totalCount/3)
			index = randomInt(0, totalCount);
		if (index>totalCount/2)
			index = randomInt(0, totalCount);

		if(index==totalCount)
			index--;
		return NameConstants.XING[index];
	}

	private static int randomInt(int from, int to) {
		Random r = new Random();
		return from + r.nextInt(to - from);
	}

	public static void main(String args[]) {
		int i=20;
		while(i>0) {
			String name = getRandomName(false);
			System.out.println(name);
			i--;
		}

	}
}


text:
import unittest
import os
import comm
from xml.etree import ElementTree
import json

class TestCrosswalkApptoolsFunctions(unittest.TestCase):

    def test_app_version_normal(self):
        comm.setUp()
        comm.create(self)
        os.chdir('org.xwalk.test')
        with open(comm.ConstPath + "/../tools/org.xwalk.test/app/manifest.json") as json_file:
            data = json.load(json_file)
        buildcmd = comm.PackTools + "crosswalk-app build"
        appVersion = comm.build(self, buildcmd)
        comm.clear("org.xwalk.test")
        self.assertEquals(data['xwalk_app_version'].strip(os.linesep), "0.1")
        self.assertEquals(data['xwalk_app_version'].strip(os.linesep), appVersion)

if __name__ == '__main__':
    unittest.main()


text:
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'shoulda/matchers'
require 'devise'

Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

RSpec.configure do |config|
  config.use_transactional_fixtures = true
  config.infer_base_class_for_anonymous_controllers = false
  config.order = "random"
  config.include FactoryGirl::Syntax::Methods
  config.filter_run focus: true
  config.run_all_when_everything_filtered = true

  config.include Devise::TestHelpers, type: :controller
  config.extend ControllerMacros, :type => :controller

  config.before(:suite) do
    begin
      DatabaseCleaner.start
    ensure
      DatabaseCleaner.clean
    end
  end
end


text:
id: v4
title: v4.x
---

## MapillaryJS `v4.x` Migration Guide

This page describes how to migrate from MapillaryJS `v3.x` to MapillaryJS `v4.x`.

## General

- Github differential - [v3.1.0...v4.0.0](https://github.com/mapillary/mapillary-js/compare/v3.1.0...v4.0.0)
- Properties named `key` in `v3.x` have been renamed to `id` throughout the library in `v4.x`

### Distribution

#### Renamed Files

| `v3.x`              | `v4.x`                    |
| ------------------- | ------------------------- |
| `mapillary.min.js`  | `mapillary.js`            |
| `mapillary.js`      | `mapillary.unminified.js` |
| `mapillary.min.css` | `mapillary.css`           |

## Module

All namespacing has been removed and the global UMD name has been changed.

### Global UMD Name

| `v3.x`      | `v4.x`      |
| ----------- | ----------- |
| `Mapillary` | `mapillary` |

### Import

#### `v3.x`

```js
import * as Mapillary from 'mapillary-js';

const viewer = new Mapillary.Viewer({...});
const marker = new Mapillary.MarkerComponent.SimpleMarker({...});
const popup = new Mapillary.PopupComponent.Popup({...});
```

#### `v4.x`

```js
import { Popup, SimpleMarker, Viewer } from 'mapillary-js';

const viewer = new Viewer({...});
const marker = new SimpleMarker({...});
const popup = new Popup({...});
```

### Destruct

#### `v3.x`

```js
const viewer = new Mapillary.Viewer({...});
const marker = new Mapillary.MarkerComponent.SimpleMarker({...});
const popup = new Mapillary.PopupComponent.Popup({...});
```

#### `v4.x`

```js
const { Popup, SimpleMarker, Viewer } = mapillary;

const viewer = new Viewer({...});
const marker = new SimpleMarker({...});
const popup = new Popup({...});
```

### Styles

All style classes have been renamed.

## Viewer

### Methods

#### Renamed

| `v3.x` | `v4.x` | Description |
| --- | --- | --- |
| `setUserToken` | `setAccessToken` | Now accepts a client access token or a user access token |

### Options

#### Added

- `trackResize` - **Breaking change:** the viewer now tracks browser window resizing by default. Set this option to false if you want to handle viewer resizing with custom logic.
- `dataProvider` - Override the default data provider.

#### Removed

| `v3.x`             | `v4.x`                                          |
| ------------------ | ----------------------------------------------- |
| `baseImageSize`    | No replacement                                  |
| `basePanoramaSize` | No replacement                                  |
| `baseImageSize`    | No replacement                                  |
| `maxImageSize`     | No replacement                                  |
| `apiClient`        | Use `dataProvider` and/or `accessToken` instead |

#### Renamed

| `v3.x`      | `v4.x`        |
| ----------- | ------------- |
| `imageKey`  | `imageId`     |
| `userToken` | `accessToken` |

### Component Options

#### Removed

| `v3.x`       | `v4.x`         |
| ------------ | -------------- |
| `background` | No replacement |
| `debug`      | No replacement |
| `route`      | No replacement |

#### Renamed

| `v3.x`        | `v4.x`    |
| ------------- | --------- |
| `imagePlane`  | `image`   |
| `mouse`       | `pointer` |
| `spatialData` | `spatial` |

#### Replaced

| `v3.x`       | `v4.x`                      |
| ------------ | --------------------------- |
| `image`      | Moved to `fallback` options |
| `navigation` | Moved to `fallback` options |

### Events

Event names are not provided as static properties on the Viewer class.

| `v3.x`                                    | `v4.x`                     |
| ----------------------------------------- | -------------------------- |
| `viewer.on(Mapillary.Viewer.click, ...);` | `viewer.on('click', ...);` |

#### Contracts

All emitted events are now an object with the following properties populated:

- `type` - Event type
- `target` - Instance that emitted the event

Additional properties are provided per event type.

#### Renamed Event Types

| `v3.x`                 | `v4.x`          |
| ---------------------- | --------------- |
| `bearingchanged`       | `bearing`       |
| `fovchanged`           | `fov`           |
| `loading`              | `dataloading`   |
| `navigablechanged`     | `navigable`     |
| `nodechanged`          | `image`         |
| `positionchanged`      | `position`      |
| `povchanged`           | `pov`           |
| `removed`              | `remove`        |
| `sequenceedgeschanged` | `sequenceedges` |
| `spatialedgeschanged`  | `spatialedges`  |

## Image

The `Node` class has been renamed to `Image`.

### Properties

#### Removed

| `v3.x`         | `v4.x`                   |
| -------------- | ------------------------ |
| `cameraUuid`   | No replacement           |
| `fullPano`     | Use `cameraType` instead |
| `gpano`        | Use `cameraType` instead |
| `pano`         | Use `cameraType` instead |
| `mergeVersion` | No replacement           |
| `projectKey`   | No replacement           |

#### Renamed

| `v3.x`                 | `v4.x`                 |
| ---------------------- | ---------------------- |
| `alt`                  | `computedAltitude`     |
| `ca`                   | `compassAngle`         |
| `cameraProjectionType` | `cameraType`           |
| `clusterKey`           | `clusterId`            |
| `computedCA`           | `computedCompassAngle` |
| `computedLatLon`       | `computedLngLat`       |
| `key`                  | `id`                   |
| `latLon`               | `lngLat`               |
| `mergeCC`              | `mergeId`              |
| `organizationKey`      | `ownerId`              |
| `orientation`          | `exifOrientation`      |
| `originalAlt`          | `originalAltitude`     |
| `originalCA`           | `originalCompassAngle` |
| `originalLatLon`       | `originalLngLat`       |
| `sequenceKey`          | `sequenceId`           |
| `userKey`              | `creatorId`            |
| `userName`             | `creatorName`          |

#### Replaced

| `v3.x`            | `v4.x`             |
| ----------------- | ------------------ |
| `focal, ck1, ck2` | `cameraParameters` |

## Types

| `v3.x` | `v4.x` |
| --- | --- |
| `ILatLon`: `{ lat: number, lon: number }` | `LngLat`: `{ lat: number, lng: number }` |
| `ILatLonAlt`: `{ alt: number, lat: number, lon: number }` | `LngLatAlt`: `{ alt: number, lat: number, lng: number }` |
| `AbortMapillaryError` | `CancelMapillaryError` |

## Enums

#### Renamed

| `v3.x`          | `v4.x`                |
| --------------- | --------------------- |
| `EdgeDirection` | `NavigationDirection` |

## Component

### Components

#### Removed

| `v3.x`       | `v4.x`                                                    |
| ------------ | --------------------------------------------------------- |
| `background` | No replacement                                            |
| `debug`      | No replacement                                            |
| `route`      | Use the custom render API or custom HTML elements instead |

#### Renamed

| `v3.x`        | `v4.x`               |
| ------------- | -------------------- |
| `imageplane`  | `image`              |
| `spatialdata` | `spatial`            |
| `image`       | `imagefallback`      |
| `navigation`  | `navigationfallback` |

### Events

| `v3.x`                                | `v4.x`            |
| ------------------------------------- | ----------------- |
| `MarkerComponent.dragend`             | `markerdragend`   |
| `MarkerComponent.dragstart`           | `markerdragstart` |
| `MarkerComponent.changed`             | `markerposition`  |
| `MarkerComponent.hoveredkeychanged`   | `hover`           |
| `SequenceComponent.hoveredkeychanged` | `hover`           |
| `SequenceComponent.playingchanged`    | `playing`         |
| `TagComponenent.geometrycreated`      | `geometrycreate`  |
| `TagComponenent.creategeometryend`    | `tagcreateend`    |
| `TagComponenent.creategeometrystart`  | `tagcreatestart`  |
| `TagComponenent.modechanged`          | `tagmode`         |
| `TagComponenent.tagschanged`          | `tags`            |
| `Tag.click`                           | `click`           |
| `Tag.geometrychanged`                 | `geometry`        |
| `Tag.changed`                         | `tag`             |

## Interaction

#### Removed

| `v3.x`                           | `v4.x`         |
| -------------------------------- | -------------- |
| `MouseComponent#doubleClickZoom` | No replacement |

## API

The complete API functionality, including ents, contracts, and providers, has been replaced. See the [v4 API reference](/api/modules/api) and examples for info about the new functionality.


text:
package io.debezium.testing.system.tools.databases.mongodb;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.debezium.testing.system.tools.databases.AbstractOcpDatabaseDeployer;
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.openshift.client.OpenShiftClient;

/**
 * @author Jakub Cechacek
 */
public class OcpMongoDeployer extends AbstractOcpDatabaseDeployer<OcpMongoController> {

    public static class Deployer extends DatabaseBuilder<OcpMongoDeployer.Deployer, OcpMongoDeployer> {
        @Override
        public OcpMongoDeployer build() {
            return new OcpMongoDeployer(
                    project,
                    deployment,
                    services,
                    ocpClient);
        }
    }

    private static final Logger LOGGER = LoggerFactory.getLogger(OcpMongoDeployer.class);

    private OcpMongoDeployer(
                             String project,
                             Deployment deployment,
                             List<Service> services,
                             OpenShiftClient ocp) {
        super(project, deployment, services, ocp);
    }

    @Override
    protected OcpMongoController getController(Deployment deployment, List<Service> services, OpenShiftClient ocp) {
        return new OcpMongoController(deployment, services, ocp);
    }
}


text:
<?xml version="1.0" encoding="UTF-8"?>
<resources>
	<string name="hello1">
		Welcome to Titanium!
	</string>
	<string name="welcome">
		Welcome to my gist
	</string>
</resources>


text:
namespace Help.CQRS
{
    public interface IApplyEvent<T> where T : Event
    {
        void Apply(T e);
    }
}


text:
require 'helper'

class User < ActiveRecord::Base
  acts_as_authentic
end

class UserSession < Authlogic::Session::Base
end

class Post < ActiveRecord::Base
  records_creating_user
end

class Note < ActiveRecord::Base
  records_creating_user :as => "user"

  def self.creatable_by?(user)
    user and user.username == "sue-create"
  end

  def readable_by?(user)
    user and user.username == "sue-read"
  end

  def editable_by?(user)
    user and user.username == "sue-edit"
  end

  def destroyable_by?(user)
    user and user.username == "sue-destroy"
  end
end

class NoteTest < ActiveSupport::TestCase
  setup :activate_authlogic
  setup { Post.destroy_all }

  should_record_creating_user :as => "user"

  should_be_creatable_by("boy named sue-create")    { Factory(:user, :username => "sue-create")  }
  should_not_be_creatable_by("everyone")            { nil }

  context "a note" do
    setup { @note = Factory(:note) }
    subject { @note }

    should_be_readable_by("boy named sue-read")       { Factory(:user, :username => "sue-read")    }
    should_be_editable_by("boy named sue-edit")       { Factory(:user, :username => "sue-edit")    }
    should_be_destroyable_by("boy named sue-destroy") { Factory(:user, :username => "sue-destroy") }

    should_not_be_readable_by(   "everyone") { nil }
    should_not_be_editable_by(   "everyone") { nil }
    should_not_be_destroyable_by("everyone") { nil }
  end
end

class PostTest < ActiveSupport::TestCase
  setup :activate_authlogic
  setup { Post.destroy_all }

  should_record_creating_user

  should_be_creatable_by("everyone") { nil }

  context "a post" do
    setup { @post = Factory(:post) }
    subject { @post }

    should_be_readable_by(   "everyone") { nil }
    should_be_editable_by(   "everyone") { nil }
    should_be_destroyable_by("everyone") { nil }
  end
end


text:
package OpenXPKI::Client::Simple;

use strict;
use warnings;
use English;
use POSIX qw( strftime );
use Getopt::Long;
use Pod::Usage;
use Data::Dumper;
use OpenXPKI::Client;
use OpenXPKI::Serialization::Simple;
use Log::Log4perl qw(:easy);

use Moose;
use Data::Dumper;

has auth => (
    is => 'rw',
    isa => 'HashRef',
    lazy => 1,
    default  => sub { return { stack => 'Anonymous', user => undef, pass => undef } }
);

has realm => (
    is => 'rw',
    isa => 'Str',
    default => '',
    lazy => 1,
);

has socketfile => (
    is => 'rw',
    isa => 'Str',
    default => '/var/openxpki/openxpki.socket',
    lazy => 1,
);

has client => (
    is => 'ro',
    isa => 'Object',
    builder  => '_build_client',
    lazy => 1,
);

has log => (
    is => 'rw',
    isa => 'Object',
    builder  => '_build_logger',
    init_arg => 'logger',
    lazy => 1,
);

has last_reply => (
    is => 'rw',
    isa => 'HashRef|Undef',
    default => undef,
);

sub _build_logger {
    Log::Log4perl->easy_init();
    return Log::Log4perl->get_logger();
};

sub _build_client {

    my $self = shift;

    my $client = OpenXPKI::Client->new({
        SOCKETFILE => $self->socketfile(),
    });

    if (! defined $client) {
        die "Could not instantiate OpenXPKI client. Stopped";
    }

    if (! $client->init_session()) {
        die "Could not initiate OpenXPKI server session. Stopped";
    }

    # run login

    my $session_id = $client->get_session_id();
    my $log = $self->log();
    $log->debug("Session id: $session_id");

    my $reply = $client->send_receive_service_msg('PING');

    my $status = $reply->{SERVICE_MSG};
    if ($status eq 'GET_PKI_REALM') {
        my $realm = $self->realm();
        if (! $realm ) {
            $log->fatal("Found more than one realm but no realm is specified");
            $log->debug("Realms found:" . Dumper (keys %{$reply->{PARAMS}->{PKI_REALMS}}));
            die "No realm specified";
        }
        $log->debug("Selecting realm $realm");
        $reply = $client->send_receive_service_msg('GET_PKI_REALM',
            { PKI_REALM => $realm });
    }

    if ($reply->{SERVICE_MSG} eq 'GET_AUTHENTICATION_STACK') {
        my $auth = $self->auth();
        if (! $auth || !$auth->{stack}) {
            $log->fatal("Found more than one auth stack but no stack is specified");
            $log->debug("Stacks found:" . Dumper (keys %{$reply->{PARAMS}->{AUTHENTICATION_STACKS}}));
            die "No auth stack specified";
        }
        $log->debug("Selecting auth stack ". $auth->{stack});
        $reply = $client->send_receive_service_msg('GET_AUTHENTICATION_STACK',
            { AUTHENTICATION_STACK => $auth->{stack} });

    }

    if ($reply->{SERVICE_MSG} eq 'GET_PASSWD_LOGIN') {
        my $auth = $self->auth();
        if (! $auth || !$auth->{stack}) {
            $log->fatal("Login/Password required but not configured");
            die "No login/password specified";
        }
        $log->debug("Do login with user ". $auth->{user});
        $reply = $client->send_receive_service_msg('GET_PASSWD_LOGIN',{
            LOGIN => $auth->{user}, PASSWD => $auth->{pass},
        });
    }

    if ($reply->{SERVICE_MSG} ne 'SERVICE_READY') {
        $log->fatal("Initialization failed - message is " . $reply->{SERVICE_MSG});
        $log->debug('Last reply: ' .Dumper $reply);
        die "Initialization failed. Stopped";
    }
    return $client;
}

sub run_command {

    my $self = shift;
    my $command = shift;
    my $params = shift || {};

    my $reply = $self->client()->send_receive_service_msg('COMMAND', {
        COMMAND => $command,
        PARAMS => $params
    });

    $self->last_reply( $reply );
    if ($reply->{SERVICE_MSG} eq 'COMMAND') {
        return $reply->{PARAMS};
    } else {
        my $message;
        if ($reply->{'LIST'} && ref $reply->{'LIST'} eq 'ARRAY') {
            # Workflow errors
            if ($reply->{'LIST'}->[0]->{PARAMS} && $reply->{'LIST'}->[0]->{PARAMS}->{__ERROR__}) {
                $message = $reply->{'LIST'}->[0]->{PARAMS}->{__ERROR__};
            } elsif($reply->{'LIST'}->[0]->{LABEL}) {
                $message = $reply->{'LIST'}->[0]->{LABEL};
            }
        } else {
            $message = 'unknown error';
        }
        $self->log()->error($message);
        die "Error running command: $message";
    }
}

sub handle_workflow {

    my $self = shift;
    my $params = shift;

    my $reply;
    # execute exisiting workflow

    # Auto serialize workflow params
    my $serializer = OpenXPKI::Serialization::Simple->new();
    foreach my $key (keys %{$params->{PARAMS}}) {
        if (ref $params->{PARAMS}->{$key}) {
            $params->{PARAMS}->{$key} = $serializer->serialize($params->{PARAMS}->{$key});
        }
    }

    if ($params->{ID}) {
        if (!$params->{ACTION}) {
            die "No action specified";
        }
        $self->log()->info(sprintf('execute workflow action %s on %01d', $params->{ACTION}, $params->{ID}));
        $self->log()->debug('workflow params:  '. Dumper $params->{PARAMS});
        $reply = $self->run_command('execute_workflow_activity',{
            ID => $params->{ID},
            ACTIVITY => $params->{ACTION},
            PARAMS => $params->{PARAMS},
        });

        if ($reply && $reply->{SERVICE_MSG} eq 'COMMAND') {
            $self->log()->debug('new Workflow State: ' . $reply->{PARAMS}->{WORKFLOW}->{STATE});
        }

    } elsif ($params->{TYPE}) {
        $reply = $self->run_command('create_workflow_instance',{
            WORKFLOW => $params->{TYPE},
            PARAMS => $params->{PARAMS},
        });
        if ($reply) {
            $self->log()->debug(sprintf('Workflow created (ID: %d), State: %s',
                $reply->{WORKFLOW}->{ID}, $reply->{WORKFLOW}->{STATE}));
        }
    } else {
        $self->log()->fatal("Neither workflow id nor type given");
        die "Neither workflow id nor type given";
    }

    return $reply;
}

sub disconnect {
    my $self = shift;
    $self->execute('LOGOUT');
    return;
}

1;

__END__

=head1 NAME