Giter Club home page Giter Club logo

utp2017-5-excel's Introduction

utp2017-5-excel

Браузерная электронная таблица

Возможности:

  • Изменение размеров таблицы
  • Редактирование содержимого ячеек. Смена цвета, стиля, размера шрифта
  • Поддержка формул
  • Обработка рекурсивных зависимостей в формулах

Разработчики:

  • Смирнов Андрей (старший) — @kupihleba
  • Кудрявцев Даниил — @crusty7
  • Примак Виктор — @Iheiko
  • Руднев Кирилл — @kir4567
  • Смирнов Максим — @SimpleCreations
  • Чекалина Елизавета — @imwritingcrapcode
  • Хизбуллина Юлия — @jkhizbullina

utp2017-5-excel's People

Contributors

ccde177 avatar crusty7 avatar imwritingcrapcode avatar jkhizbullina avatar kupihleba avatar mazdaywik avatar simplecreations avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

kupihleba

utp2017-5-excel's Issues

Баги копирования ячеек

Первый баг

  1. Пишем в ячейку A1 =1
  2. Пишем в ячейку B1 =A1
  3. Пишем в консоли ui.spreadsheet.copyCell(0, 1, 0, 2). Видим в ячейке C3 мифическое =A0.

Второй баг

  1. Пишем в ячейку A1 =1
  2. Пишем в ячейку B1 =A1
  3. Пишем в консоли ui.spreadsheet.copyCell(0, 1, 1, 1). Видим в ячейке B2 =1 и ошибку зависимости, что ничем не объясняется.

Третий баг

  1. Пишем в ячейку A1 =1
  2. Пишем в ячейку B1 =$A1
  3. Пишем в консоли ui.spreadsheet.copyCell(0, 1, 0, 2). Видим в ячейке C3 =0.

Четвертый баг

  1. Пишем в ячейку A1 =1
  2. Пишем в ячейку B1 =A$1
  3. Пишем в консоли ui.spreadsheet.copyCell(0, 1, 0, 2). Видим в ячейке C3 неожиданное =A-1.

Model: Базовая структура данных

Задача: разработать структуру данных таблица

Разработать структуру данных таблица, реализованную в виде двумерного массива.
Создать методы:

  • Изменяющие данные в клетках таблицы
  • Возвращающие значение клетки, в случае, если в ней не записана формула
  • Изменяющие размер таблицы
  • Очищающие таблицу

Model logic: Вычисление формул

Задача: Реализовать механизм хранения формул в памяти

Требуется создать метод, который парсит и сериализует формулы, сохраняя информацию для дальнейшего их вычисления.
Другими словами, представляет строку в удобо-интерпретируемом виде.

Входные данные: строка-формула
Выходные данные: объект, хранящий информацию о ссылках на ячейки таблицы и операциях, которые необходимо произвести, для вычисления значения клетки

Относительные и абсолютные адреса ячеек

Нужно добавить поддержку относительных и абсолютных адресов строк и столбцов ячеек.
Адрес абсолютный, если он не меняется при копировании или перемещении ячейки.
Если адрес строки или столбца абсолютный, перед индексом стоит символ $. Например, $A1, A$1, $A$1

  • Добавляем токены: FUNCTION, CELL_REFERENCE.
    • Если токен, который раньше был IDENTIFIER, может представлять собой только функцию, тогда этот токен записывается как FUNCTION. Пример: SUM, STRING, LOLOLOLOL, A01
    • Если токен, который раньше был IDENTIFIER, может представлять собой только ссылку на ячейку, то этот токен записывается как CELL_REFERENCE. Пример: $A1, A$99, $ZZ$666
    • Если на этапе лексического анализа нельзя определить, является токен ссылкой на ячейку или функцией, он записывается как IDENTIFIER. Примеры: A1, ZZ666, LOG10
  • Как следствие, $ входит в токен CELL_REFERENCE (или IDENTIFIER согласно грамматике). Некорректные записи вроде A$B1, $$A1, A1$ должны вызывать синтаксическую ошибку.
  • При парсинге если ссылка на ячейку содержит абсолютный адрес, нужно устанавливать свойства соответствующего объекта класса Spreadsheet._CellReference соответственно rowFixed = true | false, columnFixed = true | false

Копирование ячейки

Предварительно должна быть выполнена задача об относительных и абсолютных адресах строк и столбцов ячеек.

  • Реализуем метод move(fromRow, fromColumn, toRow, toColumn) класса Spreadsheet._CellReference. Он возвращает новый Spreadsheet._CellReference, в котором:
    • Если в исходной ссылке строка не фиксированная, индекс строки изменён на toRow - fromRow;
    • Если в исходной ссылке столбец не фиксированный, индекс столбца изменён на toColumn - fromColumn;
    • rowFixed и columnFixed имеют такие же значения.
  • Переопределяем метод toString класса Spreadsheet._Expression. Это метод "собирает" разобранное выражение обратно в строку-формулу.
  • Определяем метод generateFormula класса Spreadsheet._Cell. Он преобразует поле expression в строку и кладёт её в formula.
  • Разделяем метод setFormula на два: setFormula(i, j, formula) и setExpression(i, j, expression). Второй устанавливает пропарсенное выражение и используется в первом.
  • Реализуем метом copyCell(fromRow, fromColumn, toRow, toColumn) класса Spreadsheet. Он копирует expression из ячейки с первыми координатами рекурсивно, заменяя все _CellReference на .move(fromRow, fromColumn, toRow, toColumn), в ячейку со вторыми координатами. Затем вызывает generateFormula последней. Затем вызывает setExpression(toRow, toColumn, expression).

Model logic: Вычисление формул

Задача: Реализовать механизм вычисления формул

Требуется реализовать механизм вычисления формул в дереве разбора #8.

Model logic: Синтаксический анализатор

Задача: Создать синтаксический анализатор

Синтаксический анализатор работает методом рекурсивного спуска.
Входные данные: Последовательность токенов.
Выходные данные: Дерево разбора.

Грамматика синтаксического анализатора - #7 в БНФ

Баги парсера

  • Пустая формула (если набрать просто знак = в ячейку) не должна вызывать ошибку. Значение в событии должно быть undefined.
  • При парсинге токенов нужно проверять все символы. Некорректные символы должны вызывать синтаксическую ошибку. Сейчас если набрать =1.5, в парсере возникнет неперехваченное исключение

Добавление новых функций

Математические:

ABS(x)
ACOS(x)
ACOT(x)
ASIN(x)
ATAN(x)
CEILING(x)
COS(x)
COT(x)
DEGREES(x) — перевод x из радианов в градусы
EXP([x])
FACT(x)
FLOOR(x)
GCD(x, y)
ISEVEN(x)
ISODD(x)
LCM(x, y)
LN(x)
LOG(x, base)
LOG10(x)
MOD(dividend, divisor)
PI()
POW(base, exponent)
QUOTIENT(dividend, divisor)
RADIANS(x)
RAND() — случайное число [0, 1)
RANDBETWEEN(low, high)
ROUND(x, places)
SIGN(x)
SIN(x)
SQRT(x)
TAN(x)

Статистические:

AVERAGE(...args) — аналогично SUM, только среднее арифметическое. См. задачу про диапазоны.
COUNT(...args) — считает количество числовых значений
COUNTUNIQUE(...args) — считает количество уникальных значений
MAX(...args) — максимум; все аргументы и значения в Range должны быть все number или все string
MEDIAN(...args) — медиана
MIN(...args)
MODE(...args) — мода
PRODUCT(...args)

Строковые:

CHAR(index) — возвращает строку из одного символа под номером index в Unicode
CODE(string) — возвращает индекс в Unicode первого символа строки
FIND(needle, haystack[, startPosition])
FIXED(number, placesAfterFloatingPoint) — формат десятичного числа в виде строки
LEFT(string, length) — префикс строки длиной length
LEN(string)
LOWER(string)
MID(string, start, length) — извлечение подстроки
RIGHT(string, length) — суффикс строки длиной length
SEARCH(needle, haystack[, startPosition]) — то же, что FIND, только не чувствительная к регистру 
UPPER(string)

Управляющие:

COLUMNS(range) — ширина диапазона
IF(condition, ifTrue, ifFalse)
INDEX(range, row, column) — возвращает значение ячейки с координатами row, column относительно диапазона range
ISLOGICAL(value)
ISNUMBER(value)
ISTEXT(value)
ROWS(range) — высота диапазона

Переименовать для совместимости с другими системами управления электронными таблицами:
(Мне это тоже не нравится, но что поделать.)

EQUALS -> EQ
GREATER -> GT
GREATER_OR_EQUALS -> GTE
LESS -> LT
LESS_OR_EQUALS -> LTE
NUMBER -> N
STRING -> TEXT
NEGATE -> UNMINUS
SUBTRACT -> MINUS

Model logic: Лексический анализатор

Задача: Написать лексический анализатор

Лексический анализатор должен преобразовывать входную строку в последовательность токенов

Классификация токенов:

  • Число
  • Идентификатор — функция или ссылка на ячейку таблицы (примеры: A1, ZZ98, ABS, CONCATENATE)
  • Открывающаяся скобка (
  • Закрывающаяся скобка )
  • Оператор +, -, *, /, =, <, >, <=, >=
  • Логическая константа TRUE, FALSE
  • Строка, ограниченная символами ", причём символы \ и " могут содержаться в строке в виде \\ и \" соответственно

Токены могут разделяться любым количеством пробельных символов.

Пример формулы: CONCATENATE("Всё очень ", IF(AND(A1 >= B2 + 1.5, TRUE), "хорошо", "плохо"))

Диапазоны

Нужно добавить поддержку диапазонов как типа значений в формуле.
Пример использования: =CONCATENATE("Сумма: ", STRING(SUM(A1:A10)))

  • Добавляем токен : (COLON)
  • Создаём класс Spreadsheet._Range:
    • поле start типа Spreadsheet._CellReference — ссылка на первую угловую ячейку диапазона
    • поле end типа Spreadsheet._CellReference — ссылка на противоположную угловую ячейку
    • метод forEachCell(callback) вызвает функцию callback для каждой ячейки из диапазона, начиная с левой верхней и двигаясь справа налево, сверху вниз. callback(cell, row, column) вызывается с параметрами:
      • cell типа Spreadsheet._Cell — ячейка;
      • row, column -- координаты этой ячейки.
  • Обновлеяем парсер с учётом новой грамматики
  • В evaluate аналогично CellReference должна быть проверка, что все ячейки из диапазона существуют и определены
  • Пишем тестовую функцию SUM, код который примерно следующий:
    SUM(...args) {
        // Проверяем: количество args должно быть >= 1
        return args.reduce((sum, element) => {
              if (element instanceof Spreadsheet.Table) {
                    let rangeSum = 0;
                    element.forEachValue(cell => {
                          // Проверяем, что значение cell — number
                          rangeSum += cell.value;
                    });
                    return sum + rangeSum;
              } else if (typeof element === "number") {
                    return sum + element;
              } else {
                    // Ошибка
              }
        }, 0);
    }

Уточнение постановки задачи

Необходимо сформулировать общее представление о проекте — как будет выглядеть электронная таблица и какими функциями она будет обладать. Полученное представление следует описать в README.md в виде одного или нескольких абзацев. После этого данную задачу можно закрывать.

Импорт и экспорт формата ячеек в .xlsx

Изменения класса XLSXManager для импорта:

  • Добавляем метод import(blob) вместо fill(blob). fill() теперь не принимает аргументов и вызывается после import.
  • Добавляем метод getSelection, который возвращает {startRow, startColumn, endRow, endColumn} — диапазон сохранённой в файле выделенной области.
  • Добавляем метод getFormattedCells, который возвращает двумерный массив из FormattedCell

Для экспорта:

  • Добавляем метод setSelection(startRow, startColumn, endRow, endColumn)
  • Добавляем метод setFormattedCells(cells), где cells — двумерный массив из XLSXManager.FormattedCell.

Создаем класс XLSXManager.FormattedCell.
Он имеет поля: fontFamily, fontSize, color, bold, italic, underlined, textAlign, fillColor, borderLeft, borderTop, borderRight, borderBottom.

Создаем класс XLSXManager.FormattedCell.Border.
Он имеет поля: position, width, color.

Все поля обоих классов по умолчанию не определены.

Определенные поля XLSXManager.FormattedCell имеют значения:

  • fontSize — число точек (не пикселей).
  • bold, italic, underlinedtrue.
  • textAlign"left", "right", "center" или "justify".
  • border- — объект класса XLSXManager.FormattedCell.Border.

Определенные поля XLSXManager.FormattedCell.Border имеют значения:

  • position"top", "left", "right", "bottom".
  • width — число точек.

Итоги

Сейчас ставим оценки! Вот прямо сейчас!

Неформальный рейтинг проектов:

  1. Лидер с большим отрывом — Чат.
  2. С большим отрывом — Excel.
  3. На одном месте — Форт и Paint
  4. Графики
  5. Аутсайдер — Форум

Дубанов А. В. @alex-qrcs и Коновалов А. В. @Mazdaywik.

Баг с поиском циклических зависимостей

  • Список вершин из цикла, возвращаемый findCycleFrom, должен включать в себя все вершины из цикла, в том числе вершину, из которой производился поиск.
  • Если вершина имеет ребро из самой в себя, это тоже считается циклом, и findCycleFrom должен возвращать массив из одной этой вершины.

Ещё баги парсера

  • Не работают строки в формуле. Например, если набрать ="abc", значение в поле expression будет пустое.
  • Поле position в классе _Expression должно быть числом.
  • Некорректно обрабатываются ссылки на ячейку. Воспроизводим:
    1. Пишем в ячейку B1: =1
    2. Пишем в ячейку A1: =B1

View: Базовый сайт

Задача: Создать базовую модель сайта.

Необходимо создать эскиз сайта. По эскизу построить модель.

  • Создать наброски/эскизы/зарисовки дизайна (@jkhizbullina)
  • Выявить удобное и эргономичное расположение кнопок, панелей, полей ввода сайта
  • Подобрать легко читаемые шрифты
  • Собрать базовую модель сайта (@SimpleCreations)
    • Сделать таблицу
    • Создать панель управления таблицей (Редактирование полей таблицы, изменение размера, стиля шрифта)

Требования:

  • Чистый дизайн (использование 3-х основных цветов)
  • Использование SCSS для конфигурации элементов сайта
  • Логически правильное расположение элементов управления сайтом
  • Понятный интерфейс

Разработка архитектуры проекта и распределение ролей

Требуется разработать архитектуру электронной таблицы:

  • выбрать подходы и технологии, которые будут использоваться при разработке, а именно паттерны проектирования;
  • определить, из каких крупных компонентов будет состоять решение;
  • распределить обязанности участников между различными компонентами и различными видами деятельности, создав на каждую подзадачу «issue» и назначив её на участника.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.