public function matchesMarks(array $marks)
    {
        if (!$this->markFilter) {
            return true;
        }

        foreach ($this->markFilter as $mark => $mustBe) {

            // $mustBe has to be boolean or string, for performance reasons
            // it will not be checked again here

            if ($mustBe === true) {
                if (!isset($marks[$mark]) || !$marks[$mark]) {
                    return false;
                }
            }

            if ($mustBe === false) {
                if (!isset($marks[$mark])) {
                    continue;
                }
                if ((bool)$marks[$mark]) {
                    return false;
                }
            }

            // $mustBe cannot be boolean until here

            $shouldMatch = true;

            if (strpos($mustBe, '!') === 0) {
                $mustBe = substr($mustBe, 1);
                $shouldMatch = false;
            }

            if (!isset($marks[$mark]) && $shouldMatch) {
                return false;
            }

            if (!isset($marks[$mark]) && !$shouldMatch) {
                continue;
            }

            if ( ($marks[$mark] == $mustBe) !== $shouldMatch) {
                return false;
            }

        }

        return true;
    }