hjem

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 17, 2021 License: MIT Imports: 17 Imported by: 0

README

Hjem

Dette værktøj er designet til at støtte huskøbere til at kunne danne sig et overblik historiske købspriser for nærområdet givet man har udset sig en matrikel (hus/lejlighed).

Værktøjet er skabt pågrund at manglende indsigt for købere i boligmarkedet, som gør det svært at lave en rimelighedsbetragtning for udbudspriser uden at blive overfuset af en ejendomsmægler.

Eksempel for Østerbro 90, st. tv.

Anvendelse

Den simplest måde at anvende værktøjet på (for de fleste) er nok ved brug af Docker, det er så simpelt som at køre følgende kommando:

docker run -p 8080:8080 tpanum/hjem

Så er værktøjet tilgængeligt på addressen: http://localhost:8080. Hvis der ønsker adgang til sqlite databasen som indeholder rådata, kan den gøres tilgængelig ved at mounte /data mappen, e.g. tilføj argumentet -v /data:$(pwd)/<din_mappe_her>. Husk dog at rå data også er tilgængeligt gennem web interfacet som CSV.

Fra source

Projektet kan også køres direkte fra source, men så skal følgende steps udføres:

  1. Byg frontend: cd frontend && npm install && npm run build && cd ..
  2. Kør webserver: cd app && go run main.go

Bemærk dog at dette kræver Go (version 1.16+) og at npm er installeret.

Analyserne

Værktøjet udfører nogle projekteringer som er meget simple, og der en masse aspekter som kan have påvirket den nuværerende udbudspris som ikke afspejles ud fra projekteringerne. Disse aspekter omfatter blandt andet:

Aspekter som kan hæve prisen: Tilbygning, renovering, omstrukturering af nærområdet, øget popularitet for området, øget efterspørgsel.

Aspekter som kan sænke prisen: Faldet popularitet for området, højere udbud, ingen renovering.

Data

De priser som vises i værktøjet, har følgende karakteristika:

  • Der vises kun priser af samme typer af matrikler, som den søgte. Det er kun huspriser som anvendes når der søges på en matrikel som er et hus.
  • Priser som vises er kun dem som betegnes som almindelig fritsalg.
  • Priser er for nærområdet fra den søgte matrikel (radius fra matrikel), og er ikke påvirket af postnumre.
  • Som standard, filtreres indhentede priser som ligger langt fra normal området. Denne filtrering kan dog fjernes.

Det med småt

Værktøjer indsamler kun data fra offentligt tilgængelige kilder, men af juridiske hensyn fraskriver mig et hvert ansvaret for de opslag værktøjet skulle udføre under sin kørsel.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidZipCodes     = errors.New("invalid zip code format")
	ErrInvalidPropertyType = errors.New("invalid property type format")
	ErrUnknownAddr         = errors.New("unknown address")
)
View Source
var DefaultClient http.Client
View Source
var (
	ErrNotFoundAddr = errors.New("Unable to find address")
)
View Source
var (
	PropertyToName = map[PropertyType]string{
		PropertyHouse:       "house",
		PropertyApartment:   "apartment",
		PropertySharedHouse: "sharedhouse",
		PropertyVacation:    "vacation",
	}
)

Functions

func DanishDateToTime

func DanishDateToTime(s string, format string) time.Time

func DirtyStringToInt

func DirtyStringToInt(s string) (int, error)

func NewServer

func NewServer(db *gorm.DB) *server

func ReadListingToProperty

func ReadListingToProperty(reader io.ReadCloser, prop *BoligaProperty) error

Types

type Address

type Address struct {
	ID               uint    `json:"-" gorm:"primaryKey"`
	DawaID           string  `json:"full_txt" gorm:"not null;unique"`
	StreetName       string  `json:"street_name" gorm:"not null"`
	StreetNumber     string  `json:"street_number" gorm:"not null"`
	Floor            *string `json:"floor"`
	Door             *string `json:"door"`
	PostalCode       string  `json:"zipcode" gorm:"not null"`
	MunicipalityCode string  `json:"municipality_code" gorm:"not null"`
	Latitude         float64 `json:"lat" gorm:"not null"`
	Longtitude       float64 `json:"long" gorm:"not null"`

	BoligaCollectedAt         time.Time    `json:"-"`
	BoligaPropertyKind        PropertyType `json:"-"`
	BoligaBuildingSize        int          `json:"building_size"`
	BoligaPropertySize        int          `json:"property_size"`
	BoligaBasementSize        int          `json:"basement_size"`
	BoligaRooms               int          `json:"rooms"`
	BoligaBuiltYear           int          `json:"built_year"`
	BoligaMonthlyOwnerExpense int          `json:"monthly_owner_expense_dkk"`
	BoligaEnergyMarking       string       `json:"energy_marking"`
}

func FilterAddressesByProperty

func FilterAddressesByProperty(pt PropertyType, addrs []*Address, sales [][]Sale) ([]*Address, [][]Sale)

func (Address) Headers

func (a Address) Headers() []string

func (Address) Short

func (addr Address) Short() string

func (Address) ToSlice

func (a Address) ToSlice() []string

type Aggregation

type Aggregation struct {
	Mean int `json:"mean"`
	Std  int `json:"std"`
	N    int `json:"n"`
}

func AggregationFromPrices

func AggregationFromPrices(prices []int) Aggregation

type BoligaCacher

type BoligaCacher struct {
	// contains filtered or unexported fields
}

func NewBoligaCacher

func NewBoligaCacher(db *gorm.DB, n int) *BoligaCacher

func (*BoligaCacher) Close

func (bc *BoligaCacher) Close()

func (*BoligaCacher) FetchSales

func (bc *BoligaCacher) FetchSales(addrs []*Address) ([][]Sale, error)

type BoligaCacherResp

type BoligaCacherResp struct {
	// contains filtered or unexported fields
}

type BoligaCacherTask

type BoligaCacherTask struct {
	// contains filtered or unexported fields
}

type BoligaPageCrawl

type BoligaPageCrawl struct {
	Page        uint `gorm:"primaryKey"`
	CurrentPage int  `json:"pageIndex"`
	TotalPages  int  `json:"totalPages"`
	Error       string
	Runtime     time.Duration
	CreatedAt   time.Time
}

type BoligaProperty

type BoligaProperty struct {
	Kind                PropertyType
	BuildingSize        int
	PropertySize        int
	BasementSize        int
	Rooms               int
	BuiltYear           int
	MonthlyOwnerExpense int
	EnergyMarking       string
	Sales               []Sale
}

func PropertyFromBoligaItem

func PropertyFromBoligaItem(si BoligaSaleItem) (*BoligaProperty, error)

type BoligaPropertyRequest

type BoligaPropertyRequest struct {
	StreetName     string
	ZipCode        int
	MunicipalityID int
}

func (BoligaPropertyRequest) Fetch

type BoligaSaleItem

type BoligaSaleItem struct {
	EstateId   int       `json:"estateId"`
	EstateCode int       `json:"estateCode"`
	SoldDate   time.Time `json:"soldDate"`

	Addr             string       `json:"address"`
	Guid             string       `json:"guid"`
	MunicipalityCode int          `json:"municipalityCode"`
	AmountDKK        int          `json:"price"`
	PropertyType     PropertyType `json:"propertyType"`
	SqMeters         int          `json:"size"`
	Rooms            float64      `json:"rooms"`
	BuildYear        int          `json:"buildYear"`
	Lattitude        float64      `json:"lattitude"`
	Longtitude       float64      `json:"longtitude"`
	ZipCode          int          `json:"zipCode"`
	City             string       `json:"city"`
	PriceChange      float64      `json:"change"`
	SaleType         string       `json:"saleType"`
}

func BoligaPropertiesFromAddrs

func BoligaPropertiesFromAddrs(addrs []*Address) ([]*BoligaSaleItem, error)

type BoligaSalesResponse

type BoligaSalesResponse struct {
	Meta  BoligaPageCrawl  `json:"meta"`
	Sales []BoligaSaleItem `json:"results"`
	Err   error
}

type Config

type Config struct {
	PropertyTypes []string
	ZipCodeFrom   *int
	ZipCodeTo     *int
}

func NewConfig

func NewConfig(zipcodes, properties string) (*Config, error)

type DAWAAddress

type DAWAAddress struct {
	FullText         string  `json:"betegnelse""`
	StreetName       string  `json:"vejnavn"`
	StreetNumber     string  `json:"husnr"`
	Floor            *string `json:"etage"`
	Door             *string `json:"dør"`
	PostalCode       string  `json:"postnr"`
	MunicipalityCode string  `json:"kommunekode"`
	Latitude         float64 `json:"x"`
	Longtitude       float64 `json:"y"`
}

type DawaCacher

type DawaCacher struct {
	// contains filtered or unexported fields
}

func NewDawaCacher

func NewDawaCacher(db *gorm.DB) *DawaCacher

func (DawaCacher) Do

func (c DawaCacher) Do(req DawaRequest) ([]*Address, error)

type DawaFuzzySearch

type DawaFuzzySearch struct {
	Query string
}

func (DawaFuzzySearch) Fetch

func (dfs DawaFuzzySearch) Fetch() ([]*Address, error)

func (DawaFuzzySearch) MaxAge

func (dfs DawaFuzzySearch) MaxAge() time.Duration

func (DawaFuzzySearch) Request

func (dfs DawaFuzzySearch) Request() *http.Request

type DawaNearbySearch

type DawaNearbySearch struct {
	Addr   Address
	Meters int
}

func (DawaNearbySearch) Fetch

func (dns DawaNearbySearch) Fetch() ([]*Address, error)

func (DawaNearbySearch) MaxAge

func (dfs DawaNearbySearch) MaxAge() time.Duration

func (DawaNearbySearch) Request

func (dns DawaNearbySearch) Request() *http.Request

type DawaQueryCache

type DawaQueryCache struct {
	Query     string `gorm:"not null,unique"`
	IDs       string `gorm:"not null"`
	CreatedAt time.Time
}

func NewDawaQueryCacheFromAddrs

func NewDawaQueryCacheFromAddrs(req DawaRequest, addrs []*Address) DawaQueryCache

func (DawaQueryCache) Identifiers

func (dqc DawaQueryCache) Identifiers() []int

type DawaRequest

type DawaRequest interface {
	Request() *http.Request
	MaxAge() time.Duration
	Fetch() ([]*Address, error)
}

type DefaultHeadersTripper added in v1.0.1

type DefaultHeadersTripper struct {
	// contains filtered or unexported fields
}

func (*DefaultHeadersTripper) RoundTrip added in v1.0.1

func (t *DefaultHeadersTripper) RoundTrip(req *http.Request) (*http.Response, error)

type JSONSale

type JSONSale struct {
	AddrIndex int       `json:"addr_idx"`
	Amount    int       `json:"amount"`
	When      time.Time `json:"when"`
}

func SalesStatistics

func SalesStatistics(addrs []*Address, sales []*JSONSale, stdf int) ([]*JSONSale, map[time.Time]Aggregation)

func SeperateOutliers

func SeperateOutliers(sales []*JSONSale, prices []int, aggr Aggregation, stdf int) ([]int, []*JSONSale)

func (JSONSale) Headers

func (s JSONSale) Headers() []string

func (JSONSale) ToSlice

func (s JSONSale) ToSlice() []string

type LookupResponse

type LookupResponse struct {
	PrimaryIndex int               `json:"primary_idx"`
	Addrs        []*Address        `json:"addresses"`
	Sales        []*JSONSale       `json:"sales"`
	Ranges       map[int][]int     `json:"ranges,omitempty"`
	SquareMeters SquareMeterPrices `json:"sqmeters"`
}

func FormatLookupResponse

func FormatLookupResponse(addrs []*Address, ranges map[int][]*Address, sales [][]Sale, stdf int) (*LookupResponse, error)

type PropertyType

type PropertyType int
const (
	PropertyHouse PropertyType = iota + 1
	PropertySharedHouse
	PropertyApartment
	PropertyVacation
)

type Response

type Response struct {
	Address      string  `json:"address_name"`
	SquareMeters float64 `json:"sq_meters"`
	PropertyType `json:"property_type"`
}

type Sale

type Sale struct {
	AddrID    uint      `json:"-"`
	AmountDKK int       `json:"amount"`
	Date      time.Time `json:"time"`
}

type SalesObject

type SalesObject struct {
	Meta  *Address `json:"meta"`
	Sales []Sale   `json:"sales"`
}

type SquareMeterPrices

type SquareMeterPrices struct {
	Global      map[time.Time]Aggregation `json:"global"`
	Projections []map[time.Time]int       `json:"projections"`
}

type Store

type Store struct {
	// contains filtered or unexported fields
}

func NewStore

func NewStore(db *gorm.DB) (*Store, error)

func (*Store) CountAddresses

func (s *Store) CountAddresses() int64

func (*Store) StreamAddrs

func (s *Store) StreamAddrs(addrC <-chan Address) error

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL