private static List<Person> loadPeople(BufferedReader reader) throws IOException{
        List<String> category = new ArrayList<>();
        List<Person> people = new ArrayList<>();
        List<String> buf = new ArrayList<>();
        int size;
        String line;
        line = reader.readLine();
        //head
        splitCSVLine(buf, line);
        size = buf.size();
        for (int i = 1; i + 1 < size; i += 2) {
            String c = buf.get(i);
            String n = buf.get(i + 1);
            if (!n.isEmpty() && !c.equals(n)) {
                throw new RuntimeException("head format wrong : " + c + " != " + n);
            }
            new Option(c, loadOptionList(c), loadOptionRule(c));
            category.add(c);
        }
        Map<String, Set<String>> record = new HashMap<>();
        while ((line = reader.readLine()) != null) {
            buf.clear();
            if (splitCSVLine(buf, line).size() != size) {
                throw new RuntimeException("illegal format : row size not match head");
            }
            Person p = new Person(buf.get(0));
            for (int i = 0, len = category.size(); i < len; i++) {
                String c = category.get(i);
                List<String> tmp = Arrays.asList(buf.get(2 * i + 1).split(","));
                record.computeIfAbsent(c, k -> new HashSet<>()).addAll(tmp);
                p.self.put(c, new ArrayList<>(tmp));
                tmp = Arrays.asList(buf.get(2 * i + 2).split(","));
                record.computeIfAbsent(c, k -> new HashSet<>()).addAll(tmp);
                p.target.put(c, new ArrayList<>(tmp));
            }
            people.add(p);
        }
        record.keySet().forEach(c -> {
            Option op = Option.get(c);
            Set<String> set = record.get(c);
            set.removeIf(op::contains);
            if (!set.isEmpty()) {
                System.out.println("?" + c + set);
            }
        });
        return people;
    }