Определение ПЕРЕЧИСЛЕНИЯ MySQL в модели Django

Как я уже упоминал в комментарии, алмаз и квадрат намного легче с хорошими результатами. Таким образом, алгоритм:

  1. настраивает свойства генерации. Здесь вам нужно иметь набор параметров, таких как минимальная высота, уровень моря, уровни высоты для растительности, песок / камень / грязь и т. Д., Параметры склона и т. Д. .
  2. создать карту высоты местности. Я называю ее zed[][]. Для этого вам нужно немного модифицировать алгоритм Diamond & amp; Square . Проблема заключается в том, что этот алгоритм создает «внутренний» ландшафт. Чтобы настроить его так, чтобы он создавал островные ландшафты, вам необходимо инициализировать его с минимальным возвышением в углах. Также вам нужно проигнорировать первый шаг алмаза и инициализировать среднюю точку с помощью некоторого случайного значения (не в среднем по углам). И последний раз после каждой квадратной итерации правильная граница указывает на минимальную (подводную) высоту (или некоторое случайное значение рядом с ней). Для достижения хорошего результата я использую примерно диапазон <-2^15 , 2^16> во время генерации. После этого я нахожу минимальное и максимальное возвышение в сгенерированном ландшафте и масштабируюсь до заданных диапазонов высоты. Не забывайте, что карта с диамантом и квадратом с разрешением (2^n)+1 !!!
  3. создать карту поверхности. Я называю ее typ[][]. Когда карта местности закончена, вы можете добавить такие функции, как в порядке возрастания: watter, sand, тип растительности, горные породы, снег. Затем добавьте параметры, основанные на наклоне рельефных пород. Затем вы можете добавить дополнительные вещи, например (по некоторым правилам): реки, ручьи, водовороты, строительство, дороги, ...

Я делаю это в C ++ следующим образом:

void map_random(int _xs,int _ys)
    {
    // config
    int h0=-1000,h1=3000;       // [m] terrain elevation range
    int h_water= 0;             // [m] sea level
    int h_sand=15;              // [m] sand level
    int h_evergreen=1500;       // [m] evergreen level
    int h_snow=2000;            // [m] snow level
    int h_rock=1800;            // [m] mountine rock level
    float a_rock=60.0;          // [deg] mountine rock slope
    float d_pixel=15.0;         // [m] pixel size
    bool _island=true;

    // types
    enum _cover_enum
        {
        _cover_none=0,
        _cover_water,
        _cover_snow,
        _covers,
        _cover_shift=0,
        _cover_mask=15,
        };
    DWORD _cover[_covers]=
        {
        //  RRGGBB
        0x00000000,     // none
        0x00004080,     // water
        0x008F8F8F,     // snow
        };
    enum _terrain_enum
        {
        _terrain_enum_beg=-1,
        _terrain_dirt,
        _terrain_sand,
        _terrain_rock,
        _terrains,
        _terrain_shift=4,
        _terrain_mask=15,
        };
    DWORD _terrain[_terrains]=
        {
        //  RRGGBB
        0x00301510,     // dirt
        0x00EEC49A,     // sand
        0x00777777,     // rock
        };
    enum _flora_enum
        {
        _flora_enum_beg=-1,
        _flora_none,
        _flora_grass,
        _flora_hardwood,
        _flora_evergreen,
        _flora_deadwood,
        _floras,
        _flora_shift=8,
        _flora_mask=15,
        };
    DWORD _flora[_floras]=
        {
        //  RRGGBB
        0x00000000,     // none
        0x007F7F3F,     // grass
        0x001FFF1F,     // hardwood
        0x00007F00,     // evergreen
        0x007F3F1F,     // deadwood
        };

    // variables
    float a,b; int c,t,f;
    int x,y,z,xx,yy,mxs,mys,dx,dy,dx2,dy2,r,r2;
    int **ter=NULL,**typ=NULL;
    Randomize();
    // align resolution to power of 2
    for (mxs=1;mxs+1<_xs;mxs<<=1); if (mxs<3) mxs=3;
    for (mys=1;mys+1<_ys;mys<<=1); if (mys<3) mys=3;
    ter=new int*[mys+1]; for (y=0;y<=mys;y++) ter[y]=new int[mxs+1];
    typ=new int*[mys+1]; for (y=0;y<=mys;y++) typ[y]=new int[mxs+1];

    // [Terrain]

    // diamond & square random height map -> ter[][]
    dx=mxs; dx2=dx>>1; r=1<<16;                     // init step,half step and randomness
    dy=mys; dy2=dy>>1; r2=r>>1;
    // set corners values
    if (_island)
        {
        t=-r2;
        ter[  0][  0]=t;
        ter[  0][mxs]=t;
        ter[mys][  0]=t;
        ter[mys][mxs]=t;
        ter[dy2][dx2]=r2;
        }
    else{
        ter[  0][  0]=Random(r);
        ter[  0][mxs]=Random(r);
        ter[mys][  0]=Random(r);
        ter[mys][mxs]=Random(r);
        }
    for (;dx2|dy2;dx=dx2,dx2>>=1,dy=dy2,dy2>>=1)    // subdivide step until full image is filled
        {
        if (!dx) dx=1;
        if (!dy) dy=1;
        // diamond (skip first one for islands)
        if ((!_island)||(dx!=mxs))
         for (y=dy2,yy=mys-dy2;y<=yy;y+=dy)
          for (x=dx2,xx=mxs-dx2;x<=xx;x+=dx)
           ter[y][x]=((ter[y-dy2][x-dx2]+ter[y-dy2][x+dx2]+ter[y+dy2][x-dx2]+ter[y+dy2][x+dx2])>>2)+Random(r)-r2;
        // square
        for (y=dy2,yy=mys-dy2;y<=yy;y+=dy)
         for (x=dx ,xx=mxs-dx ;x<=xx;x+=dx)
          ter[y][x]=((ter[y][x-dx2]+ter[y][x+dx2]+ter[y-dy2][x]+ter[y+dy2][x])>>2)+Random(r)-r2;
        for (y=dy ,yy=mys-dy ;y<=yy;y+=dy)
         for (x=dx2,xx=mxs-dx2;x<=xx;x+=dx)
          ter[y][x]=((ter[y][x-dx2]+ter[y][x+dx2]+ter[y-dy2][x]+ter[y+dy2][x])>>2)+Random(r)-r2;
        for (x=dx2,xx=mxs-dx2;x<=xx;x+=dx)
            {
            y=  0; ter[y][x]=((ter[y][x-dx2]+ter[y][x+dx2]+ter[y+dy2][x])/3)+Random(r)-r2;
            y=mys; ter[y][x]=((ter[y][x-dx2]+ter[y][x+dx2]+ter[y-dy2][x])/3)+Random(r)-r2;
            }
        for (y=dy2,yy=mys-dy2;y<=yy;y+=dy)
            {
            x=  0; ter[y][x]=((ter[y][x+dx2]+ter[y-dy2][x]+ter[y+dy2][x])/3)+Random(r)-r2;
            x=mxs; ter[y][x]=((ter[y][x-dx2]+ter[y-dy2][x]+ter[y+dy2][x])/3)+Random(r)-r2;
            }

        // adjust border
        if (_island)
            {
            for (y=0;y<=mys;y+=dy2) { ter[y][0]=t; ter[y][mxs]=t; }
            for (x=0;x<=mxs;x+=dx2) { ter[0][x]=t; ter[mys][x]=t; }
            }

        // adjust randomness
        // r=(r*100)>>8; if (r<2) r=2; r2=r>>1;
        r>>=1; if (r<2) r=2; r2=r>>1;
        }
    // rescale to 
    xx=ter[0][0]; yy=xx;
    for (y=0;yz) xx=z;
        if (yy=h_snow ) c=_cover_snow;

        t=_terrain_dirt;
        if (z<=h_sand)  t=_terrain_sand;
        if (z>=h_rock)  t=_terrain_rock;
        if (a>=a_rock)  t=_terrain_rock;

        f=_flora_none;
        if (t==_terrain_dirt)
            {
            r=Random(100);
            if (r>10) f=_flora_grass;
            if (r>50)
                {
                if (z>h_evergreen) f=_flora_evergreen;
                else{
                    r=Random(h_evergreen);
                    if (r<=z) f=_flora_evergreen;
                    else      f=_flora_hardwood;
                    }
                }
            if (r<5) f=_flora_deadwood;
            }
        typ[y][x]=(c<<_cover_shift)|(t<<_terrain_shift)|(f<<_flora_shift);
        }

    // [copy data] rewrite this part to suite your needs it just compute color based on type of terrain and height
    // ter[][] is elevation in meters
    // typ[][] is surface type
/*
    for (y=0;y<_ys;y++)
     for (x=0;x<_xs;x++)
       pic.p[y][x].dd=(((ter[y][x]-h0)*255)/(h1-h0))*0x00010101;
    for (y=0;y<_ys;y++)
     for (x=0;x<_xs;x++)
        {
        r=typ[y][x];
        c=(r>>  _cover_shift)&  _cover_mask;
        t=(r>>_terrain_shift)&_terrain_mask;
        f=(r>>  _flora_shift)&  _flora_mask;
               r=_terrain[t];
        if (c) r=  _cover[c];
        if (c==_cover_water)
            {
            xx=256-((ter[y][x]<<7)/h0);
            yy=int(r>>16)&255; yy=(yy*xx)>>8; r=(r&0x0000FFFF)|(yy<<16);
            yy=int(r>> 8)&255; yy=(yy*xx)>>8; r=(r&0x00FF00FF)|(yy<< 8);
            yy=int(r    )&255; yy=(yy*xx)>>8; r=(r&0x00FFFF00)|(yy    );
            }
        if (f){ if (c) r|=_flora[f]; else r=_flora[f]; };
        pic.p[y][x+_xs].dd=r;
        }
*/    
    // free ter[][],typ[][]
    for (y=0;y<=mys;y++) delete[] ter[y]; delete[] ter; ter=NULL;
    for (y=0;y<=mys;y++) delete[] typ[y]; delete[] typ; typ=NULL;
    }

Выход с текущими настройками выглядит так:

[Примечания]

Этот подход обычно создает только один большой холм на острове. (Inland генерируется OK) Если вы хотите больше из них, вы можете создать больше карт местности и усреднить их вместе.

Вместо этого я выполняю следующие действия: я установил среднюю точку на максимальную высоту и проигнорировал первый прогон алмаза. После первого квадратного прохода я вернул среднюю точку к некоторому случайному значению. Это добавляет возможность более центральных холмов, а затем только одного. Используя этот подход и добавляя освещение (окружающее + нормальное затенение) для предварительного просмотра и небольшой настройки размера пикселя (35m), я получил этот результат:

В редких случаях это может генерировать внутреннюю карту (если центральная область слишком мала). Чтобы справиться с ней, вы можете сканировать углы для watter. Если есть земля, сгенерируйте ее снова или добавьте некоторое смещение для случайности в центральных точках на первом проходе.

Вы можете играть с кодом, например, добавить реки:

  1. найти самый верхний холм
  2. получить случайное местоположение вблизи / вокруг него
  3. set это к речному типу
  4. найти наименьший соседний пиксель высоты, не установленный к типу рек
  5. , если он находится на краю карты или установлен в режим остановки моря / воды, иначе цикл № 3 Если вы хотите более чем одна река тогда не забывает использовать какой-то временный тип для уже сделанных рек, поэтому алгоритм может работать должным образом. Вы также можете увеличить объем реки с расстояния от начала ... Вот результат: После этого вы также должны уравнять сформированную уровень воды в озере.

90
задан Josh Scholl 14 October 2013 в 14:31
поделиться

4 ответа

От документация Django :

MAYBECHOICE = (
    ('y', 'Yes'),
    ('n', 'No'),
    ('u', 'Unknown'),
)

И Вы определяете charfield в своей модели:

married = models.CharField(max_length=1, choices=MAYBECHOICE)

можно сделать то же с целочисленными полями, если Вам не нравится иметь буквы в Вашем дб.

В этом случае, перепишите свой выбор:

MAYBECHOICE = (
    (0, 'Yes'),
    (1, 'No'),
    (2, 'Unknown'),
)
106
ответ дан Robin Daugherty 24 November 2019 в 07:01
поделиться

Используя choices параметр не будет использовать ПЕРЕЧИСЛИМЫЙ тип дб; это просто создаст VARCHAR или ЦЕЛОЕ ЧИСЛО, в зависимости от того, используете ли Вы choices с CharField или IntegerField. Обычно это очень хорошо. Если для Вас важно, чтобы ПЕРЕЧИСЛИМЫЙ тип использовался на уровне базы данных, у Вас есть три опции:

  1. Использование "./manage.py sql appname" для наблюдения SQL, который Django генерирует, вручную измените его, чтобы использовать ПЕРЕЧИСЛИМЫЙ тип и выполнить его сами. Если Вы составите таблицу вручную сначала, то "./manage.py syncdb" не смешает с нею.
  2. , Если Вы не хотите делать это вручную каждый раз, Вы генерируете свой DB, помещаете некоторый пользовательский SQL в appname/sql/modelname.sql для выполнения соответствующей команды ALTER TABLE.
  3. Создают пользовательский тип поля и определяют db_type метод соответственно.

С любой из этих опций, это была бы Ваша обязанность иметь дело с последствиями для мобильности перекрестной базы данных. В опции 2 Вы могли использовать database-backend-specific пользовательский SQL, чтобы гарантировать, что Ваш ALTER TABLE только выполняется на MySQL. В опции 3 Ваш db_type метод должен был бы проверить механизм базы данных и установить тип столбца дб на тип, который на самом деле существует в той базе данных.

ОБНОВЛЕНИЕ : Так как платформа миграций была добавлена в Django 1.7, опции 1 и 2 выше являются совершенно устаревшими. Опция 3 всегда была наилучшим вариантом так или иначе. Новая версия опций 1/2 включила бы сложную пользовательскую миграцию с помощью SeparateDatabaseAndState - но действительно Вы хотите опцию 3.

32
ответ дан Carl Meyer 24 November 2019 в 07:01
поделиться

Если Вы действительно хотите использовать свой тип баз данных ENUM:

  1. Использование Django 1.x
  2. Распознает, что Ваше приложение будет только работать над некоторыми базами данных.
  3. Ломают голову над этой страницей документации: http://docs.djangoproject.com/en/dev/howto/custom-model-fields/#howto-custom-model-fields

Удачи!

6
ответ дан Charles Merriam 24 November 2019 в 07:01
поделиться
from django.db import models

class EnumField(models.Field):
    """
    A field class that maps to MySQL's ENUM type.

    Usage:

    class Card(models.Model):
        suit = EnumField(values=('Clubs', 'Diamonds', 'Spades', 'Hearts'))

    c = Card()
    c.suit = 'Clubs'
    c.save()
    """
    def __init__(self, *args, **kwargs):
        self.values = kwargs.pop('values')
        kwargs['choices'] = [(v, v) for v in self.values]
        kwargs['default'] = self.values[0]
        super(EnumField, self).__init__(*args, **kwargs)

    def db_type(self):
        return "enum({0})".format( ','.join("'%s'" % v for v in self.values) )
36
ответ дан 24 November 2019 в 07:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: