Cara menulis pernyataan beralih di Ruby


Jawaban:


2671

Ruby menggunakan caseekspresi sebagai gantinya.

case x
when 1..5
  "It's between 1 and 5"
when 6
  "It's 6"
when "foo", "bar"
  "It's either foo or bar"
when String
  "You passed a string"
else
  "You gave me #{x} -- I have no idea what to do with that."
end

Ruby membandingkan objek dalam whenklausa dengan objek dalam caseklausa menggunakan ===operator. Misalnya 1..5 === x,, dan tidak x === 1..5.

Ini memungkinkan whenklausa canggih seperti yang terlihat di atas. Kisaran, kelas, dan segala macam hal dapat diuji bukan hanya untuk kesetaraan.

Tidak seperti switchpernyataan dalam banyak bahasa lain, Ruby casetidak memiliki fall-through , jadi tidak perlu mengakhiri masing when- masing dengan a break. Anda juga dapat menentukan beberapa kecocokan dalam satu whenklausa seperti when "foo", "bar".


12
Anda juga dapat melakukan regex pada argumen yang diteruskan: ketika / thisisregex / baris berikutnya menyatakan "Ini adalah kecocokan yang ditemukan no. 1 # {$ 1}" end
Automatico

8
Juga patut dicatat, Anda dapat mempersingkat kode Anda dengan meletakkan whendan returnpernyataan pada baris yang sama:when "foo" then "bar"
Alexander - Reinstate Monica

9
Penting: Tidak seperti switchpernyataan dalam banyak bahasa lain, Ruby caseTIDAK memiliki fall-through , jadi tidak perlu mengakhiri masing when- masing dengan a break.
janniks

3
Begitu banyak suara tetapi belum menyebutkan kata kunci then. Silakan juga lihat jawaban lainnya.
Clint Pachl

442

case...whenberperilaku agak tidak terduga ketika menangani kelas. Ini disebabkan oleh fakta bahwa ia menggunakan ===operator.

Operator itu berfungsi seperti yang diharapkan dengan literal, tetapi tidak dengan kelas:

1 === 1           # => true
Fixnum === Fixnum # => false

Ini berarti bahwa jika Anda ingin melakukan case ... whenlebih dari satu kelas objek, ini tidak akan berfungsi:

obj = 'hello'
case obj.class
when String
  print('It is a string')
when Fixnum
  print('It is a number')
else
  print('It is not a string or number')
end

Akan mencetak "Ini bukan string atau angka".

Untungnya, ini mudah diselesaikan. The ===Operator telah didefinisikan sehingga mengembalikan truejika Anda menggunakannya dengan kelas dan menyediakan sebuah instance dari kelas yang sebagai operan kedua:

Fixnum === 1 # => true

Singkatnya, kode di atas dapat diperbaiki dengan menghapus .class:

obj = 'hello'
case obj  # was case obj.class
when String
  print('It is a string')
when Fixnum
  print('It is a number')
else
  print('It is not a string or number')
end

Saya mendapatkan masalah ini hari ini sambil mencari jawaban, dan ini adalah halaman pertama yang muncul, jadi saya pikir itu akan bermanfaat bagi orang lain dalam situasi yang sama.


obj = 'hello'; obj kasus; ketika 'halo' lalu menempatkan "Ini halo" berakhir
Sugumar Venkatesan

Memiliki .classbagian dalam menarik untuk dicatat, terima kasih. Tentu saja, ini sepenuhnya perilaku yang sesuai (meskipun saya bisa melihat bagaimana mungkin kesalahan umum untuk berpikir yang akan mencetak It is a string) ... Anda sedang menguji kelas dari beberapa objek yang arbitrer, bukan objek itu sendiri. Jadi, misalnya: case 'hello'.class when String then "String!" when Class then "Class!" else "Something else" endhasil dalam: "Class!"Ini bekerja sama untuk 1.class, {}.class, dll menjatuhkan .class, kita mendapatkan "String!"atau "Something else"untuk berbagai nilai-nilai.
lindes

219

Ini dilakukan menggunakan casedi Ruby. Lihat juga " Alihkan pernyataan " di Wikipedia.

Dikutip:

case n
when 0
  puts 'You typed zero'
when 1, 9
  puts 'n is a perfect square'
when 2
  puts 'n is a prime number'
  puts 'n is an even number'
when 3, 5, 7
  puts 'n is a prime number'
when 4, 6, 8
  puts 'n is an even number'
else
  puts 'Only single-digit numbers are allowed'
end

Contoh lain:

score = 70

result = case score
   when 0..40 then "Fail"
   when 41..60 then "Pass"
   when 61..70 then "Pass with Merit"
   when 71..100 then "Pass with Distinction"
   else "Invalid Score"
end

puts result

Pada sekitar halaman 123 dari Bahasa Pemrograman Ruby (Edisi 1, O'Reilly) di Kindle saya, dikatakan thenkata kunci yang mengikuti whenklausa dapat diganti dengan baris baru atau titik koma (seperti dalam if then elsesintaksis). (Ruby 1.8 juga memungkinkan titik dua di tempatnya then, tetapi sintaks ini tidak lagi diizinkan di Ruby 1.9.)


38
when (-1.0/0.0)..-1 then "Epic fail"
Andrew Grimm

Ini adalah jawaban yang saya gunakan, karena saya mendefinisikan variabel berdasarkan hasil dari saklar kasus. Daripada mengatakan type = #{score}setiap baris, saya hanya dapat menyalin apa yang Anda lakukan. Jauh lebih elegan. Saya juga menyukai one-liner yang jauh lebih baik (jika mungkin)
onebree

Saya tahu ini tidak terkait dengan esensi jawabannya, tetapi 4 juga merupakan kuadrat sempurna.
Nick Moore

109

kasus ... kapan

Untuk menambahkan lebih banyak contoh ke jawaban Chuck :

Dengan parameter:

case a
when 1
  puts "Single value"
when 2, 3
  puts "One of comma-separated values"
when 4..6
  puts "One of 4, 5, 6"
when 7...9
  puts "One of 7, 8, but not 9"
else
  puts "Any other thing"
end

Tanpa parameter:

case
when b < 3
  puts "Little than 3"
when b == 3
  puts "Equal to 3"
when (1..10) === b
  puts "Something in closed range of [1..10]"
end

Harap waspadai " Cara menulis pernyataan beralih di Ruby " yang diperingatkan kikito.


Terima kasih, ini sangat membantu karena memiliki beberapa opsi pada satu baris. Saya telah mencoba untuk menggunakanor
sixty4bit

73

Banyak bahasa pemrograman, terutama yang berasal dari C, memiliki dukungan untuk apa yang disebut Switch Fallthrough . Saya sedang mencari cara terbaik untuk melakukan hal yang sama di Ruby dan berpikir itu mungkin berguna bagi orang lain:

Dalam bahasa seperti C, fallthrough biasanya terlihat seperti ini:

switch (expression) {
    case 'a':
    case 'b':
    case 'c':
        // Do something for a, b or c
        break;
    case 'd':
    case 'e':
        // Do something else for d or e
        break;
}

Di Ruby, hal yang sama dapat dicapai dengan cara berikut:

case expression
when 'a', 'b', 'c'
  # Do something for a, b or c
when 'd', 'e'
  # Do something else for d or e
end

Ini tidak sepenuhnya setara, karena tidak mungkin untuk 'a'mengeksekusi blok kode sebelum jatuh ke 'b'atau 'c', tetapi sebagian besar saya merasa cukup mirip untuk berguna dengan cara yang sama.


72

Di Ruby 2.0, Anda juga dapat menggunakan lambdas dalam casepernyataan, sebagai berikut:

is_even = ->(x) { x % 2 == 0 }

case number
when 0 then puts 'zero'
when is_even then puts 'even'
else puts 'odd'
end

Anda juga dapat membuat komparator sendiri dengan mudah menggunakan Struct dengan custom ===

Moddable = Struct.new(:n) do
  def ===(numeric)
    numeric % n == 0
  end
end

mod4 = Moddable.new(4)
mod3 = Moddable.new(3)

case number
when mod4 then puts 'multiple of 4'
when mod3 then puts 'multiple of 3'
end

(Contoh diambil dari " Bisakah procs digunakan dengan pernyataan kasus di Ruby 2.0? ".)

Atau, dengan kelas lengkap:

class Vehicle
  def ===(another_vehicle)
    self.number_of_wheels == another_vehicle.number_of_wheels
  end
end

four_wheeler = Vehicle.new 4
two_wheeler = Vehicle.new 2

case vehicle
when two_wheeler
  puts 'two wheeler'
when four_wheeler
  puts 'four wheeler'
end

(Contoh diambil dari " Bagaimana Pernyataan Kasus Ruby Bekerja Dan Apa Yang Dapat Anda Lakukan dengannya ".)


52

Anda dapat menggunakan ekspresi reguler, seperti menemukan jenis string:

case foo
when /^(true|false)$/
   puts "Given string is boolean"
when /^[0-9]+$/ 
   puts "Given string is integer"
when /^[0-9\.]+$/
   puts "Given string is float"
else
   puts "Given string is probably string"
end

Ruby caseakan menggunakan operan kesetaraan ===untuk ini (terima kasih @JimDeville). Informasi tambahan tersedia di " Operator Ruby ". Ini juga dapat dilakukan dengan menggunakan contoh @mmdemirbas (tanpa parameter), hanya pendekatan ini yang lebih bersih untuk jenis kasus ini.



33

Ini disebut casedan berfungsi seperti yang Anda harapkan, ditambah banyak hal menyenangkan lainnya ===yang mengimplementasikan tes.

case 5
  when 5
    puts 'yes'
  else
    puts 'else'
end

Sekarang untuk bersenang-senang:

case 5 # every selector below would fire (if first)
  when 3..7    # OK, this is nice
  when 3,4,5,6 # also nice
  when Fixnum  # or
  when Integer # or
  when Numeric # or
  when Comparable # (?!) or
  when Object  # (duhh) or
  when Kernel  # (?!) or
  when BasicObject # (enough already)
    ...
end

Dan ternyata Anda juga dapat mengganti rantai arbitrer if / else (yaitu, bahkan jika tes tidak melibatkan variabel umum) dengan casedengan meninggalkan caseparameter awal dan hanya menulis ekspresi di mana kecocokan pertama adalah yang Anda inginkan.

case
  when x.nil?
    ...
  when (x.match /'^fn'/)
    ...
  when (x.include? 'substring')
    ...
  when x.gsub('o', 'z') == 'fnzrq'
    ...
  when Time.now.tuesday?
    ...
end

23

Ruby menggunakan casepergantian pernyataan penulisan.

Sesuai casedokumentasi:

Pernyataan kasus terdiri dari kondisi opsional, yang berada dalam posisi argumen case, dan nol atau lebih whenklausa. whenKlausa pertama yang cocok dengan kondisi (atau untuk mengevaluasi kebenaran Boolean, jika kondisinya nol) “menang”, dan bait kodenya dieksekusi. Nilai pernyataan kasus adalah nilai whenklausa yang berhasil , atau niljika tidak ada klausa tersebut.

Pernyataan kasus dapat diakhiri dengan elseklausa. Setiap whenpernyataan dapat memiliki beberapa nilai kandidat, dipisahkan dengan koma.

Contoh:

case x
when 1,2,3
  puts "1, 2, or 3"
when 10
  puts "10"
else
  puts "Some other number"
end

Versi lebih pendek:

case x
when 1,2,3 then puts "1, 2, or 3"
when 10 then puts "10"
else puts "Some other number"
end

Dan seperti " Pernyataan kasus Ruby - teknik-teknik canggih " menggambarkan Ruby case;

Dapat digunakan dengan Ranges :

case 5
when (1..10)
  puts "case statements match inclusion in a range"
end

## => "case statements match inclusion in a range"

Dapat digunakan dengan Regex :

case "FOOBAR"
when /BAR$/
  puts "they can match regular expressions!"
end

## => "they can match regular expressions!"

Dapat digunakan dengan Procs dan Lambdas :

case 40
when -> (n) { n.to_s == "40" }
  puts "lambdas!"
end

## => "lambdas"

Juga, dapat digunakan dengan kelas pertandingan Anda sendiri:

class Success
  def self.===(item)
    item.status >= 200 && item.status < 300
  end
end

class Empty
  def self.===(item)
    item.response_size == 0
  end
end

case http_response
when Empty
  puts "response was empty"
when Success
  puts "response was a success"
end

22

Tergantung pada kasus Anda, Anda dapat memilih untuk menggunakan metode hash.

Jika ada daftar panjang whens dan masing-masing memiliki nilai konkret untuk dibandingkan dengan (bukan interval), akan lebih efektif untuk mendeklarasikan hash metode dan kemudian memanggil metode yang relevan dari hash seperti itu.

# Define the hash
menu = {a: :menu1, b: :menu2, c: :menu2, d: :menu3}

# Define the methods
def menu1
  puts 'menu 1'
end

def menu2
  puts 'menu 2'
end

def menu3
  puts 'menu3'
end

# Let's say we case by selected_menu = :a
selected_menu = :a

# Then just call the relevant method from the hash
send(menu[selected_menu])

21

Karena switch caseselalu mengembalikan satu objek, kami dapat langsung mencetak hasilnya:

puts case a
     when 0
        "It's zero"
     when 1
        "It's one"
     end

20

Kasus multi-nilai kapan dan tanpa nilai:

print "Enter your grade: "
grade = gets.chomp
case grade
when "A", "B"
  puts 'You pretty smart!'
when "C", "D"
  puts 'You pretty dumb!!'
else
  puts "You can't even use a computer!"
end

Dan solusi ekspresi reguler di sini:

print "Enter a string: "
some_string = gets.chomp
case
when some_string.match(/\d/)
  puts 'String has numbers'
when some_string.match(/[a-zA-Z]/)
  puts 'String has letters'
else
  puts 'String has no numbers or letters'
end

2
mengapa tidak adil case some_string, when /\d/, (stuff), when /[a-zA-Z]/, (stuff), end(di mana ,berarti baris baru)
tckmn

2
oh, dan bagian pertama sudah dibahas dalam jawaban ini , dan banyak jawaban sudah menyebutkan regex. Terus terang, jawaban ini tidak menambahkan sesuatu yang baru, dan saya downvoting dan memilih untuk menghapusnya.
tckmn

@DoorknobofSnow Ini untuk menunjukkan bahwa Anda dapat menggunakan solusi Regex dan koma nilai-nilai yang dipisahkan dalam case switch. Tidak yakin mengapa solusinya membuat Anda sangat sakit.
123

jadi jika mereka mendapat "F", nilai yang sah, itu salah mereka kode Anda tidak ada case?
Mike Graf

Saya suka humor ini, dan fakta bahwa itu menunjukkan bahwa Anda dapat mencocokkan string dengan kasus.
Amril

13

Anda dapat menulis caseekspresi dengan dua cara berbeda di Ruby:

  1. Mirip dengan serangkaian ifpernyataan
  2. Tentukan target di sebelah casedan setiap whenklausa dibandingkan dengan target.
age = 20
case 
when age >= 21
puts "display something"
when 1 == 0
puts "omg"
else
puts "default condition"
end

atau:

case params[:unknown]
when /Something/ then 'Nothing'
when /Something else/ then 'I dont know'
end

Meskipun kode Anda mungkin menjawab pertanyaan, Anda harus menambahkan setidaknya deskripsi singkat tentang apa yang kode Anda lakukan dan bagaimana memecahkan masalah awal.
user1438038

Saya akan mempertimbangkan tip ini di masa depan.
ysk

10

Anda dapat melakukannya seperti ini dengan cara yang lebih alami,

case expression
when condtion1
   function
when condition2
   function
else
   function
end

9

Banyak jawaban bagus tapi saya pikir saya akan menambahkan satu factoid .. Jika Anda mencoba untuk membandingkan objek (Kelas) pastikan Anda memiliki metode kapal ruang (bukan lelucon) atau mengerti bagaimana mereka dibandingkan

" Ruby Equality And Object Comparison " adalah diskusi yang baik tentang topik tersebut.


7
Untuk referensi, metode "space-ship" adalah <=>, yang digunakan untuk mengembalikan -1, 0, 1, atau nil tergantung pada apakah perbandingan mengembalikan kurang dari, sama, lebih besar dari, atau tidak sebanding masing-masing. Dokumentasi modul Sebanding Ruby menjelaskannya.
the Tin Man

7

Sebagaimana dinyatakan dalam banyak jawaban di atas, ===operator digunakan di bawah kap pernyataan case/ whenpernyataan.

Berikut ini informasi tambahan tentang operator itu:

Operator kesetaraan kasus: ===

Banyak kelas bawaan Ruby, seperti String, Range, dan Regexp, menyediakan implementasi ===operator mereka sendiri , juga dikenal sebagai "kesetaraan kasus", "triple equals" atau "threequals". Karena diimplementasikan secara berbeda di setiap kelas, ia akan berperilaku berbeda tergantung pada jenis objek yang dipanggil. Secara umum, ia mengembalikan true jika objek di sebelah kanan "milik" atau "adalah anggota" objek di sebelah kiri. Misalnya, ini dapat digunakan untuk menguji apakah suatu objek adalah turunan dari kelas (atau salah satu dari sub-kelasnya).

String === "zen"  # Output: => true
Range === (1..2)   # Output: => true
Array === [1,2,3]   # Output: => true
Integer === 2   # Output: => true

Hasil yang sama dapat dicapai dengan metode lain yang mungkin paling cocok untuk pekerjaan itu, seperti is_a?dan instance_of?.

Rentang Implementasi ===

Ketika ===operator dipanggil pada objek jangkauan, itu mengembalikan true jika nilai di sebelah kanan jatuh dalam rentang di sebelah kiri.

(1..4) === 3  # Output: => true
(1..4) === 2.345 # Output: => true
(1..4) === 6  # Output: => false

("a".."d") === "c" # Output: => true
("a".."d") === "e" # Output: => false

Ingat bahwa ===operator memanggil ===metode objek kiri. Begitu (1..4) === 3juga dengan (1..4).=== 3. Dengan kata lain, kelas operan kiri akan menentukan implementasi ===metode yang akan dipanggil, sehingga posisi operan tidak dapat dipertukarkan.

Implementasi Regexp dari ===

Mengembalikan nilai true jika string di sebelah kanan cocok dengan ekspresi reguler di sebelah kiri.

/zen/ === "practice zazen today"  # Output: => true
# is similar to
"practice zazen today"=~ /zen/

Satu-satunya perbedaan yang relevan antara dua contoh di atas adalah bahwa, ketika ada kecocokan, ===mengembalikan true dan =~mengembalikan integer, yang merupakan nilai sebenarnya di Ruby. Kami akan segera kembali ke sini.


5
puts "Recommend me a language to learn?"
input = gets.chomp.downcase.to_s

case input
when 'ruby'
    puts "Learn Ruby"
when 'python'
    puts "Learn Python"
when 'java'
    puts "Learn Java"
when 'php'
    puts "Learn PHP"
else
    "Go to Sleep!"
end

1
Ini lebih membantu jika Anda memberikan penjelasan mengapa ini adalah solusi yang disukai dan menjelaskan cara kerjanya. Kami ingin mendidik, bukan hanya memberikan kode.
the Tin Man

3
$age =  5
case $age
when 0 .. 2
   puts "baby"
when 3 .. 6
   puts "little child"
when 7 .. 12
   puts "child"
when 13 .. 18
   puts "youth"
else
   puts "adult"
end

Lihat " Ruby - if ... else, case, kecuali " untuk informasi lebih lanjut.


1

Saya sudah mulai menggunakan:

a = "secondcase"

var_name = case a
  when "firstcase" then "foo"
  when "secondcase" then "bar"
end

puts var_name
>> "bar"

Ini membantu kode ringkas dalam beberapa kasus.


1
Kode seperti ini biasanya harus dilakukan dengan menggunakan Hash, daripada casepernyataan.
Tom Lord

Menggunakan hash akan lebih cepat saat sakelar itu menjadi besar.
the Tin Man

1

Tidak ada dukungan untuk ekspresi reguler di lingkungan Anda? Misalnya Editor Skrip Shopify (April, 2018):

[Kesalahan]: RegExp konstan tidak diinisialisasi

Solusi yang mengikuti kombinasi metode yang sebelumnya telah dibahas di sini dan di sini :

code = '!ADD-SUPER-BONUS!'

class StrContains
  def self.===(item)
    item.include? 'SUPER' or item.include? 'MEGA' or\
    item.include? 'MINI' or item.include? 'UBER'
  end
end

case code.upcase
when '12345PROMO', 'CODE-007', StrContains
  puts "Code #{code} is a discount code!"
when '!ADD-BONUS!'
  puts 'This is a bonus code!'
else
  puts 'Sorry, we can\'t do anything with the code you added...'
end

Saya menggunakan ors dalam pernyataan metode kelas karena ||memiliki prioritas lebih tinggi daripada .include?. Jika Anda seorang ruby-nazi , tolong bayangkan saya menggunakan ini (item.include? 'A') || ...sebagai gantinya. tes repl.it.


1

Sangat penting untuk menekankan koma ( ,) dalam whenklausa. Ini bertindak sebagai ||sebuah ifpernyataan, yaitu, hal itu merupakan OR perbandingan dan bukan DAN perbandingan antara ekspresi dibatasi dari whenklausa. Lihat pernyataan kasus berikut:

x = 3
case x
  when 3, x < 2 then 'apple'
  when 3, x > 2 then 'orange'
end
 => "apple"

xtidak kurang dari 2, namun nilai kembalinya adalah "apple". Mengapa? Karena x3 dan sejak ',`` acts as an|| , it did not bother to evaluate the expressionx <2 '.

Anda mungkin berpikir bahwa untuk melakukan DAN , Anda dapat melakukan sesuatu seperti ini di bawah, tetapi tidak berhasil:

case x
  when (3 && x < 2) then 'apple'
  when (3 && x > 2) then 'orange'
end
 => nil 

Itu tidak bekerja karena (3 && x > 2)mengevaluasi ke true, dan Ruby mengambil nilai True dan membandingkannya xdengan ===, yang tidak benar, karena xadalah 3.

Untuk melakukan &&perbandingan, Anda harus memperlakukan caseseperti if/ elseblok:

case
  when x == 3 && x < 2 then 'apple'
  when x == 3 && x > 2 then 'orange'
end

Dalam buku Bahasa Pemrograman Ruby, Matz mengatakan formulir terakhir ini adalah formulir sederhana (dan jarang digunakan), yang tidak lebih dari sintaks alternatif untuk if/ elsif/ else. Namun, apakah itu jarang digunakan atau tidak, saya tidak melihat cara lain untuk melampirkan banyak &&ekspresi untuk whenklausa yang diberikan .


Ini sepertinya bukan gaya pengkodean yang bagus untuk saya. Menggunakan sintaks alternatif yang jarang mengaburkan tidak perlu. Mengapa tidak menggunakan normal if...elsif? Tampaknya Anda mencoba mencampur pernyataan kasus dan kondisi. Mengapa? Masukkan saja kondisional ke dalam blok when, mis. when 3; ( x < 2 ) ? 'apple' : 'orange'
sondra.kinsey

0

Kita dapat menulis pernyataan beralih untuk berbagai kondisi.

Sebagai contoh,

x = 22

CASE x
  WHEN 0..14 THEN puts "#{x} is less than 15"    
  WHEN 15 THEN puts "#{x} equals 15" 
  WHEN 15 THEN puts "#{x} equals 15" 
  WHEN 15..20 THEN puts "#{x} is greater than 15" 
  ELSE puts "Not in the range, value #{x} " 
END

1
Ini tidak akan berhasil; Ruby kata kunci (misalnya. case, when, end) Adalah case-sensitive dan tidak bisa huruf besar seperti ini.
sondra.kinsey

NoMethodError (undefined method CASE 'untuk main: Object) `. Seperti yang dikatakan @ sondra.kinsey, Anda tidak dapat menggunakan huruf besar. Ruby akan berpikir itu adalah KONSTAN.
the Tin Man

0

The caseOperator pernyataan seperti switchdalam bahasa-bahasa lain.

Ini adalah sintaks dari switch...casedalam C:

switch (expression)
​{
    case constant1:
      // statements
      break;
    case constant2:
      // statements
      break;
    .
    .
    .
    default:
      // default statements
}

Ini adalah sintaks case...whendalam Ruby:

case expression
  when constant1, constant2 #Each when statement can have multiple candidate values, separated by commas.
     # statements 
     next # is like continue in other languages
  when constant3
     # statements 
     exit # exit is like break in other languages
  .
  .
  .
  else
     # statements
end

Sebagai contoh:

x = 10
case x
when 1,2,3
  puts "1, 2, or 3"
  exit
when 10
  puts "10" # it will stop here and execute that line
  exit # then it'll exit
else
  puts "Some other number"
end

Untuk informasi lebih lanjut, lihat casedokumentasi.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.