view common/Objects.cpp @ 4:719a4f477098 classical-rdf

* Add Classical Archives composer list importer; run it
author Chris Cannam
date Thu, 10 Dec 2009 15:15:40 +0000
parents 29ca5974905d
children d35e5d769c87
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */

#include "Objects.h"

#include <dataquay/Debug.h>

#include <cstdlib>
#include <iostream>

#include <QHash> // to ensure correct qHash(const QString &) is found

unsigned int
qHash(const QUrl &u)
{
    return qHash(u.toString());
}

namespace ClassicalData {

QMap<QString, Form *> Form::m_map;
QMutex Form::m_mutex;

bool
Composer::datesMatch(const Composer *b) const
{
    const Composer *a = this;
    
    if (a->birth() && b->birth()) {
        int ay = a->birth()->year(), by = b->birth()->year();
        if (ay < 1800 || // birth dates before 1700 tend to be vague!
            a->birth()->approximate() ||
            b->birth()->approximate()) {
            if (abs(ay - by) > 25) return false;
        } else {
            if (abs(ay - by) > 1) {
                return false;
            }
        }
    }
    if (a->death() && b->death()) {
        int ay = a->death()->year(), by = b->death()->year();
        if (a->death()->approximate() || b->death()->approximate()) {
            if (abs(ay - by) > 10) return false;
        } else if (ay < 1700) {
            if (abs(ay - by) > 25) return false;
        } else if (ay < 1800) {
            // cut a bit of slack, but not as much as for birth date
            if (abs(ay - by) > 10) return false;
        } else {
            if (abs(ay - by) > 1) return false;
        }
    }
    return true;
}

QString
Composer::getSortName(bool caps) const
{
    QString n = name();
    QStringList pl = n.split(QRegExp(", *"));
    if (pl.size() == 1) {
        QStringList pl2;
        pl = n.split(' ');
        pl2.push_back(pl[pl.size()-1]);
        pl2.push_back("");
        for (int i = 0; i+1 < pl.size(); ++i) {
            if (i > 0) pl2[1] += " ";
            pl2[1] += pl[i];
        }
        pl = pl2;
    }
    if (caps) {
        n = pl[0].toUpper();
    } else {
        n = pl[0];
    }
    for (int i = 1; i < pl.size(); ++i) {
        n += ", ";
        n += pl[i];
    }
    return n;
}

QString
Composer::getDisplayDates() const
{
    QString s;
    if (birth() || death()) {
        bool showApprox = false;
        if ((birth() && birth()->approximate()) ||
            (death() && death()->approximate())) {
            showApprox = true;
        }
        if (birth()) {
            if (birth()->place() != "") {
                s += birth()->place() + ", ";
            }
            if (showApprox) {
                s += "c. ";
                showApprox = false;
            }
            s += QString("%1").arg(birth()->year());
        }
        s += "-";
        if (death()) {
            if (death()->place() != "") {
                s += death()->place() + ", ";
            }
            if (showApprox) {
                s += "c. ";
                showApprox = false;
            }
            s += QString("%1").arg(death()->year());
        }
    }

    return s;
}

static int
compare(QString a, QString b)
{
    if (a < b) {
        return -1;
    } else if (a > b) {
        return 1;
    } else {
        return 0;
    }
}

static int
compareNumericTexts(QString a, QString b)
{
//    std::cout << "compare " << a.toStdString()
//              << " " << b.toStdString() << std::endl;

    if (a == b) return 0;

    if (!a[0].isDigit()) {
        if (!b[0].isDigit()) {
            QStringList al = a.split(QRegExp("[ :-]"));
            QStringList bl = b.split(QRegExp("[ :-]"));
            if (al.size() < 2 || bl.size() < 2 ||
                al.size() != bl.size()) {
                if (a < b) return -1;
                else if (a > b) return 1;
                else return 0;
            }
            for (int i = 0; i < al.size(); ++i) {
                if (al[i] != bl[i]) {
//                    std::cout << "subcompare " << al[i].toStdString()
//                              << " " << bl[i].toStdString() << std::endl;
                    return compareNumericTexts(al[i], bl[i]);
                }
            }
        } else {
            return compare(a, b);
        }
    } else {
        if (!b[0].isDigit()) {
            return compare(a, b);
        }
    }
    
    // use atoi instead of toInt() because we want it to succeed even
    // if the text is not only an integer (e.g. 35a)
    int aoi = atoi(a.toLocal8Bit().data());
    int boi = atoi(b.toLocal8Bit().data());

//    std::cout << "aoi = " << aoi << ", boi = " << boi << std::endl;

    if (aoi == boi) return compare(a, b);
    else return aoi - boi;
}

bool
Work::Ordering::operator()(Work *a, Work *b)
{
    if (!a) {
        if (!b) return false;
        else return true;
    } else {
        if (!b) {
            return false;
        }
    }
/*
    QString ao = a->catalogue();
    if (ao == "") ao = a->opus();

    QString bo = b->catalogue();
    if (bo == "") bo = b->opus();

    std::cout << "ao " << ao.toStdString() << ", bo " << bo.toStdString() << std::endl;
*/
    int c = 0;
    if (a->catalogue() != "" && b->catalogue() != "") {
        c = compareNumericTexts(a->catalogue(), b->catalogue());
    }
    if (c == 0 && a->opus() != "" && b->opus() != "") {
        c = compareNumericTexts(a->opus(), b->opus());
    }
    if (c == 0 && a->partOf() == b->partOf() &&
        a->number() != "" && b->number() != "") {
        c = compareNumericTexts(a->number(), b->number());
    }

    bool rv = false;

    if (c == 0) {
        if (a->name() == b->name()) rv = (a < b);
        else rv = (a->name() < b->name());
    } else {
        rv = (c < 0);
    }

//    std::cout << "result = " << rv << std::endl;
    return rv;
}


}